iwa 0.0.0__py3-none-any.whl → 0.0.1a2__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 (191) hide show
  1. conftest.py +22 -0
  2. iwa/__init__.py +1 -0
  3. iwa/__main__.py +6 -0
  4. iwa/core/__init__.py +1 -0
  5. iwa/core/chain/__init__.py +68 -0
  6. iwa/core/chain/errors.py +47 -0
  7. iwa/core/chain/interface.py +514 -0
  8. iwa/core/chain/manager.py +38 -0
  9. iwa/core/chain/models.py +128 -0
  10. iwa/core/chain/rate_limiter.py +193 -0
  11. iwa/core/cli.py +210 -0
  12. iwa/core/constants.py +28 -0
  13. iwa/core/contracts/__init__.py +1 -0
  14. iwa/core/contracts/contract.py +297 -0
  15. iwa/core/contracts/erc20.py +79 -0
  16. iwa/core/contracts/multisend.py +71 -0
  17. iwa/core/db.py +317 -0
  18. iwa/core/keys.py +361 -0
  19. iwa/core/mnemonic.py +385 -0
  20. iwa/core/models.py +344 -0
  21. iwa/core/monitor.py +209 -0
  22. iwa/core/plugins.py +45 -0
  23. iwa/core/pricing.py +91 -0
  24. iwa/core/services/__init__.py +17 -0
  25. iwa/core/services/account.py +57 -0
  26. iwa/core/services/balance.py +113 -0
  27. iwa/core/services/plugin.py +88 -0
  28. iwa/core/services/safe.py +392 -0
  29. iwa/core/services/transaction.py +172 -0
  30. iwa/core/services/transfer/__init__.py +166 -0
  31. iwa/core/services/transfer/base.py +260 -0
  32. iwa/core/services/transfer/erc20.py +247 -0
  33. iwa/core/services/transfer/multisend.py +386 -0
  34. iwa/core/services/transfer/native.py +262 -0
  35. iwa/core/services/transfer/swap.py +326 -0
  36. iwa/core/settings.py +95 -0
  37. iwa/core/tables.py +60 -0
  38. iwa/core/test.py +27 -0
  39. iwa/core/tests/test_wallet.py +255 -0
  40. iwa/core/types.py +59 -0
  41. iwa/core/ui.py +99 -0
  42. iwa/core/utils.py +59 -0
  43. iwa/core/wallet.py +380 -0
  44. iwa/plugins/__init__.py +1 -0
  45. iwa/plugins/gnosis/__init__.py +5 -0
  46. iwa/plugins/gnosis/cow/__init__.py +6 -0
  47. iwa/plugins/gnosis/cow/quotes.py +148 -0
  48. iwa/plugins/gnosis/cow/swap.py +403 -0
  49. iwa/plugins/gnosis/cow/types.py +20 -0
  50. iwa/plugins/gnosis/cow_utils.py +44 -0
  51. iwa/plugins/gnosis/plugin.py +68 -0
  52. iwa/plugins/gnosis/safe.py +157 -0
  53. iwa/plugins/gnosis/tests/test_cow.py +227 -0
  54. iwa/plugins/gnosis/tests/test_safe.py +100 -0
  55. iwa/plugins/olas/__init__.py +5 -0
  56. iwa/plugins/olas/constants.py +106 -0
  57. iwa/plugins/olas/contracts/activity_checker.py +93 -0
  58. iwa/plugins/olas/contracts/base.py +10 -0
  59. iwa/plugins/olas/contracts/mech.py +49 -0
  60. iwa/plugins/olas/contracts/mech_marketplace.py +43 -0
  61. iwa/plugins/olas/contracts/service.py +215 -0
  62. iwa/plugins/olas/contracts/staking.py +403 -0
  63. iwa/plugins/olas/importer.py +736 -0
  64. iwa/plugins/olas/mech_reference.py +135 -0
  65. iwa/plugins/olas/models.py +110 -0
  66. iwa/plugins/olas/plugin.py +243 -0
  67. iwa/plugins/olas/scripts/test_full_mech_flow.py +259 -0
  68. iwa/plugins/olas/scripts/test_simple_lifecycle.py +74 -0
  69. iwa/plugins/olas/service_manager/__init__.py +60 -0
  70. iwa/plugins/olas/service_manager/base.py +113 -0
  71. iwa/plugins/olas/service_manager/drain.py +336 -0
  72. iwa/plugins/olas/service_manager/lifecycle.py +839 -0
  73. iwa/plugins/olas/service_manager/mech.py +322 -0
  74. iwa/plugins/olas/service_manager/staking.py +530 -0
  75. iwa/plugins/olas/tests/conftest.py +30 -0
  76. iwa/plugins/olas/tests/test_importer.py +128 -0
  77. iwa/plugins/olas/tests/test_importer_error_handling.py +349 -0
  78. iwa/plugins/olas/tests/test_mech_contracts.py +85 -0
  79. iwa/plugins/olas/tests/test_olas_contracts.py +249 -0
  80. iwa/plugins/olas/tests/test_olas_integration.py +561 -0
  81. iwa/plugins/olas/tests/test_olas_models.py +144 -0
  82. iwa/plugins/olas/tests/test_olas_view.py +258 -0
  83. iwa/plugins/olas/tests/test_olas_view_actions.py +137 -0
  84. iwa/plugins/olas/tests/test_olas_view_modals.py +120 -0
  85. iwa/plugins/olas/tests/test_plugin.py +70 -0
  86. iwa/plugins/olas/tests/test_plugin_full.py +212 -0
  87. iwa/plugins/olas/tests/test_service_lifecycle.py +150 -0
  88. iwa/plugins/olas/tests/test_service_manager.py +1065 -0
  89. iwa/plugins/olas/tests/test_service_manager_errors.py +208 -0
  90. iwa/plugins/olas/tests/test_service_manager_flows.py +497 -0
  91. iwa/plugins/olas/tests/test_service_manager_mech.py +135 -0
  92. iwa/plugins/olas/tests/test_service_manager_rewards.py +360 -0
  93. iwa/plugins/olas/tests/test_service_manager_validation.py +145 -0
  94. iwa/plugins/olas/tests/test_service_staking.py +342 -0
  95. iwa/plugins/olas/tests/test_staking_integration.py +269 -0
  96. iwa/plugins/olas/tests/test_staking_validation.py +109 -0
  97. iwa/plugins/olas/tui/__init__.py +1 -0
  98. iwa/plugins/olas/tui/olas_view.py +952 -0
  99. iwa/tools/check_profile.py +67 -0
  100. iwa/tools/release.py +111 -0
  101. iwa/tools/reset_env.py +111 -0
  102. iwa/tools/reset_tenderly.py +362 -0
  103. iwa/tools/restore_backup.py +82 -0
  104. iwa/tui/__init__.py +1 -0
  105. iwa/tui/app.py +174 -0
  106. iwa/tui/modals/__init__.py +5 -0
  107. iwa/tui/modals/base.py +406 -0
  108. iwa/tui/rpc.py +63 -0
  109. iwa/tui/screens/__init__.py +1 -0
  110. iwa/tui/screens/wallets.py +749 -0
  111. iwa/tui/tests/test_app.py +125 -0
  112. iwa/tui/tests/test_rpc.py +139 -0
  113. iwa/tui/tests/test_wallets_refactor.py +30 -0
  114. iwa/tui/tests/test_widgets.py +123 -0
  115. iwa/tui/widgets/__init__.py +5 -0
  116. iwa/tui/widgets/base.py +100 -0
  117. iwa/tui/workers.py +42 -0
  118. iwa/web/dependencies.py +76 -0
  119. iwa/web/models.py +76 -0
  120. iwa/web/routers/accounts.py +115 -0
  121. iwa/web/routers/olas/__init__.py +24 -0
  122. iwa/web/routers/olas/admin.py +169 -0
  123. iwa/web/routers/olas/funding.py +135 -0
  124. iwa/web/routers/olas/general.py +29 -0
  125. iwa/web/routers/olas/services.py +378 -0
  126. iwa/web/routers/olas/staking.py +341 -0
  127. iwa/web/routers/state.py +65 -0
  128. iwa/web/routers/swap.py +617 -0
  129. iwa/web/routers/transactions.py +153 -0
  130. iwa/web/server.py +155 -0
  131. iwa/web/tests/test_web_endpoints.py +713 -0
  132. iwa/web/tests/test_web_olas.py +430 -0
  133. iwa/web/tests/test_web_swap.py +103 -0
  134. iwa-0.0.1a2.dist-info/METADATA +234 -0
  135. iwa-0.0.1a2.dist-info/RECORD +186 -0
  136. iwa-0.0.1a2.dist-info/entry_points.txt +2 -0
  137. iwa-0.0.1a2.dist-info/licenses/LICENSE +21 -0
  138. iwa-0.0.1a2.dist-info/top_level.txt +4 -0
  139. tests/legacy_cow.py +248 -0
  140. tests/legacy_safe.py +93 -0
  141. tests/legacy_transaction_retry_logic.py +51 -0
  142. tests/legacy_tui.py +440 -0
  143. tests/legacy_wallets_screen.py +554 -0
  144. tests/legacy_web.py +243 -0
  145. tests/test_account_service.py +120 -0
  146. tests/test_balance_service.py +186 -0
  147. tests/test_chain.py +490 -0
  148. tests/test_chain_interface.py +210 -0
  149. tests/test_cli.py +139 -0
  150. tests/test_contract.py +195 -0
  151. tests/test_db.py +180 -0
  152. tests/test_drain_coverage.py +174 -0
  153. tests/test_erc20.py +95 -0
  154. tests/test_gnosis_plugin.py +111 -0
  155. tests/test_keys.py +449 -0
  156. tests/test_legacy_wallet.py +1285 -0
  157. tests/test_main.py +13 -0
  158. tests/test_mnemonic.py +217 -0
  159. tests/test_modals.py +109 -0
  160. tests/test_models.py +213 -0
  161. tests/test_monitor.py +202 -0
  162. tests/test_multisend.py +84 -0
  163. tests/test_plugin_service.py +119 -0
  164. tests/test_pricing.py +143 -0
  165. tests/test_rate_limiter.py +199 -0
  166. tests/test_reset_tenderly.py +202 -0
  167. tests/test_rpc_view.py +73 -0
  168. tests/test_safe_coverage.py +139 -0
  169. tests/test_safe_service.py +168 -0
  170. tests/test_service_manager_integration.py +61 -0
  171. tests/test_service_manager_structure.py +31 -0
  172. tests/test_service_transaction.py +176 -0
  173. tests/test_staking_router.py +71 -0
  174. tests/test_staking_simple.py +31 -0
  175. tests/test_tables.py +76 -0
  176. tests/test_transaction_service.py +161 -0
  177. tests/test_transfer_multisend.py +179 -0
  178. tests/test_transfer_native.py +220 -0
  179. tests/test_transfer_security.py +93 -0
  180. tests/test_transfer_structure.py +37 -0
  181. tests/test_transfer_swap_unit.py +155 -0
  182. tests/test_ui_coverage.py +66 -0
  183. tests/test_utils.py +53 -0
  184. tests/test_workers.py +91 -0
  185. tools/verify_drain.py +183 -0
  186. __init__.py +0 -2
  187. hello.py +0 -6
  188. iwa-0.0.0.dist-info/METADATA +0 -10
  189. iwa-0.0.0.dist-info/RECORD +0 -6
  190. iwa-0.0.0.dist-info/top_level.txt +0 -2
  191. {iwa-0.0.0.dist-info → iwa-0.0.1a2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,208 @@
1
+ """Error handling tests for Olas ServiceManager."""
2
+
3
+ from unittest.mock import MagicMock, patch
4
+
5
+ import pytest
6
+
7
+ from iwa.plugins.olas.contracts.staking import StakingState
8
+ from iwa.plugins.olas.models import Service
9
+ from iwa.plugins.olas.service_manager import ServiceManager, ServiceState
10
+
11
+ VALID_ADDR = "0x1234567890123456789012345678901234567890"
12
+
13
+
14
+ @pytest.fixture
15
+ def mock_wallet():
16
+ """Create a mock wallet for tests."""
17
+ wallet = MagicMock()
18
+ wallet.master_account.address = VALID_ADDR
19
+ wallet.chain_interface.chain_name = "gnosis"
20
+ wallet.sign_and_send_transaction.return_value = (True, {"transactionHash": b"\x00" * 32})
21
+ wallet.key_storage.create_account.return_value.address = VALID_ADDR
22
+ wallet.key_storage.get_account.return_value.address = VALID_ADDR
23
+ return wallet
24
+
25
+
26
+ def setup_manager(mock_wallet):
27
+ """Setup a ServiceManager with mocked dependencies."""
28
+ with patch("iwa.plugins.olas.service_manager.base.Config") as mock_cfg_cls:
29
+ mock_cfg = mock_cfg_cls.return_value
30
+ mock_cfg.plugins = {"olas": MagicMock()}
31
+ mock_cfg.plugins["olas"].get_service.return_value = None
32
+ with patch(
33
+ "iwa.plugins.olas.service_manager.OLAS_CONTRACTS",
34
+ {
35
+ "gnosis": {
36
+ "OLAS_SERVICE_REGISTRY": VALID_ADDR,
37
+ "OLAS_SERVICE_MANAGER": VALID_ADDR,
38
+ "OLAS_MECH": VALID_ADDR,
39
+ }
40
+ },
41
+ ):
42
+ with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_if_cls:
43
+ mock_if = mock_if_cls.return_value
44
+ mock_if.get.return_value.chain.name.lower.return_value = "gnosis"
45
+ mock_if.get.return_value.get_contract_address.return_value = VALID_ADDR
46
+ manager = ServiceManager(mock_wallet)
47
+ manager.registry = MagicMock()
48
+ manager.manager_contract = MagicMock()
49
+ manager.olas_config = mock_cfg.plugins["olas"]
50
+ manager.chain_name = "gnosis"
51
+ manager.registry.chain_interface.get_contract_address.return_value = VALID_ADDR
52
+ return manager
53
+
54
+
55
+ def test_service_manager_mech_requests_failures(mock_wallet):
56
+ """Test failure paths in mech requests."""
57
+ manager = setup_manager(mock_wallet)
58
+
59
+ # Service missing
60
+ manager.service = None
61
+ assert manager.send_mech_request(b"data") is None
62
+
63
+ manager.service = Service(
64
+ service_name="t",
65
+ chain_name="gnosis",
66
+ service_id=1,
67
+ agent_ids=[1],
68
+ multisig_address=VALID_ADDR,
69
+ )
70
+
71
+ # Marketplace failures
72
+ with patch("iwa.plugins.olas.service_manager.mech.MechMarketplaceContract") as mock_mkt_cls:
73
+ mock_mkt = mock_mkt_cls.return_value
74
+
75
+ # No marketplace address
76
+ with patch("iwa.plugins.olas.service_manager.OLAS_CONTRACTS", {"gnosis": {}}):
77
+ assert manager.send_mech_request(b"data", use_marketplace=True) is None
78
+
79
+ # No priority_mech
80
+ assert manager.send_mech_request(b"data", use_marketplace=True, priority_mech=None) is None
81
+
82
+ # Invalid priority mech factory
83
+ mock_mkt.call.return_value = "0x0000000000000000000000000000000000000000"
84
+ assert (
85
+ manager.send_mech_request(b"data", use_marketplace=True, priority_mech=VALID_ADDR)
86
+ is None
87
+ )
88
+
89
+ # No priority mech factory multisig
90
+ mock_mkt.call.side_effect = ["0x1234", "0x0000000000000000000000000000000000000000"]
91
+ assert (
92
+ manager.send_mech_request(b"data", use_marketplace=True, priority_mech=VALID_ADDR)
93
+ is None
94
+ )
95
+
96
+ # Legacy failures
97
+ # Legacy mech address missing
98
+ with patch("iwa.plugins.olas.service_manager.OLAS_CONTRACTS", {"gnosis": {}}):
99
+ assert manager.send_mech_request(b"data", use_marketplace=False) is None
100
+
101
+
102
+ def test_service_manager_lifecycle_failures(mock_wallet):
103
+ """Test failure paths in lifecycle methods."""
104
+ manager = setup_manager(mock_wallet)
105
+ manager.service = Service(service_name="t", chain_name="gnosis", service_id=1, agent_ids=[1])
106
+
107
+ # register_agent failures
108
+ # Initial state mismatch for agent registration
109
+ manager.registry.get_service.return_value = {"state": ServiceState.PRE_REGISTRATION}
110
+ assert manager.register_agent() is False
111
+
112
+ # stake failures
113
+ # Initial state mismatch for staking
114
+ manager.service.staking_contract_address = VALID_ADDR
115
+ manager.registry.get_service.return_value = {"state": ServiceState.PRE_REGISTRATION}
116
+ mock_staking = MagicMock()
117
+ mock_staking.staking_token_address = VALID_ADDR
118
+ mock_staking.get_requirements.return_value = {
119
+ "staking_token": VALID_ADDR,
120
+ "min_staking_deposit": 50000000000000000000,
121
+ "num_agent_instances": 1,
122
+ "required_agent_bond": 50000000000000000000,
123
+ }
124
+ with patch("iwa.plugins.olas.service_manager.staking.ERC20Contract"):
125
+ assert manager.stake(mock_staking) is False
126
+
127
+ # unstake failures
128
+ # Service not staked
129
+ manager.service.staking_contract_address = None
130
+ mock_staking = MagicMock()
131
+ mock_staking.get_staking_state.return_value = StakingState.NOT_STAKED
132
+ assert manager.unstake(mock_staking) is False
133
+
134
+ # unbond failures
135
+ # Event missing in unbond
136
+ manager.registry.get_service.return_value = {"state": ServiceState.TERMINATED_BONDED}
137
+ mock_wallet.sign_and_send_transaction.return_value = (True, {"transactionHash": b"hex"})
138
+ manager.registry.extract_events.return_value = []
139
+ # manager.manager is what is used in unbond (line 523)
140
+ manager.manager = MagicMock()
141
+ assert manager.unbond() is False
142
+
143
+ # spin_up/wind_down failure log lines
144
+ manager.registry.get_service.return_value = {"state": ServiceState.DEPLOYED}
145
+ assert manager.spin_up() is True
146
+
147
+ manager.registry.get_service.return_value = {"state": ServiceState.PRE_REGISTRATION}
148
+ assert manager.wind_down() is True
149
+
150
+
151
+ def test_service_manager_staking_status_failures(mock_wallet):
152
+ """Test failure paths in get_staking_status."""
153
+ manager = setup_manager(mock_wallet)
154
+
155
+ # Service missing
156
+ manager.service = None
157
+ assert manager.get_staking_status() is None
158
+
159
+ manager.service = Service(service_name="t", chain_name="gnosis", service_id=1, agent_ids=[1])
160
+ # Staking contract missing
161
+ manager.service.staking_contract_address = None
162
+ status = manager.get_staking_status()
163
+ assert status.is_staked is False
164
+
165
+ # Exception in contract loading
166
+ manager.service.staking_contract_address = VALID_ADDR
167
+ with patch("iwa.plugins.olas.service_manager.staking.StakingContract") as mock_staking_cls:
168
+ mock_staking_cls.side_effect = Exception("fail")
169
+ status = manager.get_staking_status()
170
+ assert status.staking_state == "ERROR"
171
+
172
+ # Exception in get_service_info
173
+ mock_staking_cls.side_effect = None
174
+ mock_staking = mock_staking_cls.return_value
175
+ mock_staking.get_staking_state.return_value = StakingState.STAKED
176
+ mock_staking.get_service_info.side_effect = Exception("fail")
177
+ status = manager.get_staking_status()
178
+ assert status.is_staked is True
179
+ assert status.mech_requests_this_epoch == 0
180
+
181
+
182
+ def test_service_manager_verify_event_exception(mock_wallet):
183
+ """Test exception path in _execute_mech_tx."""
184
+ manager = setup_manager(mock_wallet)
185
+ manager.service = Service(
186
+ service_name="t",
187
+ chain_name="gnosis",
188
+ service_id=1,
189
+ agent_ids=[1],
190
+ multisig_address=VALID_ADDR,
191
+ )
192
+
193
+ # EOA path
194
+
195
+ with patch.object(manager.wallet.account_service, "resolve_account") as mock_resolve:
196
+ mock_resolve.return_value = MagicMock()
197
+ mock_resolve.return_value.__class__ = object
198
+
199
+ # Exception in extract_events
200
+ with patch.object(
201
+ manager.registry.chain_interface.web3.eth, "wait_for_transaction_receipt"
202
+ ) as mock_wait:
203
+ mock_wait.return_value = {"logs": []}
204
+ manager.registry.extract_events.side_effect = Exception("fail")
205
+ assert (
206
+ manager._execute_mech_tx({"data": "0x"}, VALID_ADDR, manager.registry, "Event")
207
+ is None
208
+ )