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.
- conftest.py +22 -0
- iwa/__init__.py +1 -0
- iwa/__main__.py +6 -0
- iwa/core/__init__.py +1 -0
- iwa/core/chain/__init__.py +68 -0
- iwa/core/chain/errors.py +47 -0
- iwa/core/chain/interface.py +514 -0
- iwa/core/chain/manager.py +38 -0
- iwa/core/chain/models.py +128 -0
- iwa/core/chain/rate_limiter.py +193 -0
- iwa/core/cli.py +210 -0
- iwa/core/constants.py +28 -0
- iwa/core/contracts/__init__.py +1 -0
- iwa/core/contracts/contract.py +297 -0
- iwa/core/contracts/erc20.py +79 -0
- iwa/core/contracts/multisend.py +71 -0
- iwa/core/db.py +317 -0
- iwa/core/keys.py +361 -0
- iwa/core/mnemonic.py +385 -0
- iwa/core/models.py +344 -0
- iwa/core/monitor.py +209 -0
- iwa/core/plugins.py +45 -0
- iwa/core/pricing.py +91 -0
- iwa/core/services/__init__.py +17 -0
- iwa/core/services/account.py +57 -0
- iwa/core/services/balance.py +113 -0
- iwa/core/services/plugin.py +88 -0
- iwa/core/services/safe.py +392 -0
- iwa/core/services/transaction.py +172 -0
- iwa/core/services/transfer/__init__.py +166 -0
- iwa/core/services/transfer/base.py +260 -0
- iwa/core/services/transfer/erc20.py +247 -0
- iwa/core/services/transfer/multisend.py +386 -0
- iwa/core/services/transfer/native.py +262 -0
- iwa/core/services/transfer/swap.py +326 -0
- iwa/core/settings.py +95 -0
- iwa/core/tables.py +60 -0
- iwa/core/test.py +27 -0
- iwa/core/tests/test_wallet.py +255 -0
- iwa/core/types.py +59 -0
- iwa/core/ui.py +99 -0
- iwa/core/utils.py +59 -0
- iwa/core/wallet.py +380 -0
- iwa/plugins/__init__.py +1 -0
- iwa/plugins/gnosis/__init__.py +5 -0
- iwa/plugins/gnosis/cow/__init__.py +6 -0
- iwa/plugins/gnosis/cow/quotes.py +148 -0
- iwa/plugins/gnosis/cow/swap.py +403 -0
- iwa/plugins/gnosis/cow/types.py +20 -0
- iwa/plugins/gnosis/cow_utils.py +44 -0
- iwa/plugins/gnosis/plugin.py +68 -0
- iwa/plugins/gnosis/safe.py +157 -0
- iwa/plugins/gnosis/tests/test_cow.py +227 -0
- iwa/plugins/gnosis/tests/test_safe.py +100 -0
- iwa/plugins/olas/__init__.py +5 -0
- iwa/plugins/olas/constants.py +106 -0
- iwa/plugins/olas/contracts/activity_checker.py +93 -0
- iwa/plugins/olas/contracts/base.py +10 -0
- iwa/plugins/olas/contracts/mech.py +49 -0
- iwa/plugins/olas/contracts/mech_marketplace.py +43 -0
- iwa/plugins/olas/contracts/service.py +215 -0
- iwa/plugins/olas/contracts/staking.py +403 -0
- iwa/plugins/olas/importer.py +736 -0
- iwa/plugins/olas/mech_reference.py +135 -0
- iwa/plugins/olas/models.py +110 -0
- iwa/plugins/olas/plugin.py +243 -0
- iwa/plugins/olas/scripts/test_full_mech_flow.py +259 -0
- iwa/plugins/olas/scripts/test_simple_lifecycle.py +74 -0
- iwa/plugins/olas/service_manager/__init__.py +60 -0
- iwa/plugins/olas/service_manager/base.py +113 -0
- iwa/plugins/olas/service_manager/drain.py +336 -0
- iwa/plugins/olas/service_manager/lifecycle.py +839 -0
- iwa/plugins/olas/service_manager/mech.py +322 -0
- iwa/plugins/olas/service_manager/staking.py +530 -0
- iwa/plugins/olas/tests/conftest.py +30 -0
- iwa/plugins/olas/tests/test_importer.py +128 -0
- iwa/plugins/olas/tests/test_importer_error_handling.py +349 -0
- iwa/plugins/olas/tests/test_mech_contracts.py +85 -0
- iwa/plugins/olas/tests/test_olas_contracts.py +249 -0
- iwa/plugins/olas/tests/test_olas_integration.py +561 -0
- iwa/plugins/olas/tests/test_olas_models.py +144 -0
- iwa/plugins/olas/tests/test_olas_view.py +258 -0
- iwa/plugins/olas/tests/test_olas_view_actions.py +137 -0
- iwa/plugins/olas/tests/test_olas_view_modals.py +120 -0
- iwa/plugins/olas/tests/test_plugin.py +70 -0
- iwa/plugins/olas/tests/test_plugin_full.py +212 -0
- iwa/plugins/olas/tests/test_service_lifecycle.py +150 -0
- iwa/plugins/olas/tests/test_service_manager.py +1065 -0
- iwa/plugins/olas/tests/test_service_manager_errors.py +208 -0
- iwa/plugins/olas/tests/test_service_manager_flows.py +497 -0
- iwa/plugins/olas/tests/test_service_manager_mech.py +135 -0
- iwa/plugins/olas/tests/test_service_manager_rewards.py +360 -0
- iwa/plugins/olas/tests/test_service_manager_validation.py +145 -0
- iwa/plugins/olas/tests/test_service_staking.py +342 -0
- iwa/plugins/olas/tests/test_staking_integration.py +269 -0
- iwa/plugins/olas/tests/test_staking_validation.py +109 -0
- iwa/plugins/olas/tui/__init__.py +1 -0
- iwa/plugins/olas/tui/olas_view.py +952 -0
- iwa/tools/check_profile.py +67 -0
- iwa/tools/release.py +111 -0
- iwa/tools/reset_env.py +111 -0
- iwa/tools/reset_tenderly.py +362 -0
- iwa/tools/restore_backup.py +82 -0
- iwa/tui/__init__.py +1 -0
- iwa/tui/app.py +174 -0
- iwa/tui/modals/__init__.py +5 -0
- iwa/tui/modals/base.py +406 -0
- iwa/tui/rpc.py +63 -0
- iwa/tui/screens/__init__.py +1 -0
- iwa/tui/screens/wallets.py +749 -0
- iwa/tui/tests/test_app.py +125 -0
- iwa/tui/tests/test_rpc.py +139 -0
- iwa/tui/tests/test_wallets_refactor.py +30 -0
- iwa/tui/tests/test_widgets.py +123 -0
- iwa/tui/widgets/__init__.py +5 -0
- iwa/tui/widgets/base.py +100 -0
- iwa/tui/workers.py +42 -0
- iwa/web/dependencies.py +76 -0
- iwa/web/models.py +76 -0
- iwa/web/routers/accounts.py +115 -0
- iwa/web/routers/olas/__init__.py +24 -0
- iwa/web/routers/olas/admin.py +169 -0
- iwa/web/routers/olas/funding.py +135 -0
- iwa/web/routers/olas/general.py +29 -0
- iwa/web/routers/olas/services.py +378 -0
- iwa/web/routers/olas/staking.py +341 -0
- iwa/web/routers/state.py +65 -0
- iwa/web/routers/swap.py +617 -0
- iwa/web/routers/transactions.py +153 -0
- iwa/web/server.py +155 -0
- iwa/web/tests/test_web_endpoints.py +713 -0
- iwa/web/tests/test_web_olas.py +430 -0
- iwa/web/tests/test_web_swap.py +103 -0
- iwa-0.0.1a2.dist-info/METADATA +234 -0
- iwa-0.0.1a2.dist-info/RECORD +186 -0
- iwa-0.0.1a2.dist-info/entry_points.txt +2 -0
- iwa-0.0.1a2.dist-info/licenses/LICENSE +21 -0
- iwa-0.0.1a2.dist-info/top_level.txt +4 -0
- tests/legacy_cow.py +248 -0
- tests/legacy_safe.py +93 -0
- tests/legacy_transaction_retry_logic.py +51 -0
- tests/legacy_tui.py +440 -0
- tests/legacy_wallets_screen.py +554 -0
- tests/legacy_web.py +243 -0
- tests/test_account_service.py +120 -0
- tests/test_balance_service.py +186 -0
- tests/test_chain.py +490 -0
- tests/test_chain_interface.py +210 -0
- tests/test_cli.py +139 -0
- tests/test_contract.py +195 -0
- tests/test_db.py +180 -0
- tests/test_drain_coverage.py +174 -0
- tests/test_erc20.py +95 -0
- tests/test_gnosis_plugin.py +111 -0
- tests/test_keys.py +449 -0
- tests/test_legacy_wallet.py +1285 -0
- tests/test_main.py +13 -0
- tests/test_mnemonic.py +217 -0
- tests/test_modals.py +109 -0
- tests/test_models.py +213 -0
- tests/test_monitor.py +202 -0
- tests/test_multisend.py +84 -0
- tests/test_plugin_service.py +119 -0
- tests/test_pricing.py +143 -0
- tests/test_rate_limiter.py +199 -0
- tests/test_reset_tenderly.py +202 -0
- tests/test_rpc_view.py +73 -0
- tests/test_safe_coverage.py +139 -0
- tests/test_safe_service.py +168 -0
- tests/test_service_manager_integration.py +61 -0
- tests/test_service_manager_structure.py +31 -0
- tests/test_service_transaction.py +176 -0
- tests/test_staking_router.py +71 -0
- tests/test_staking_simple.py +31 -0
- tests/test_tables.py +76 -0
- tests/test_transaction_service.py +161 -0
- tests/test_transfer_multisend.py +179 -0
- tests/test_transfer_native.py +220 -0
- tests/test_transfer_security.py +93 -0
- tests/test_transfer_structure.py +37 -0
- tests/test_transfer_swap_unit.py +155 -0
- tests/test_ui_coverage.py +66 -0
- tests/test_utils.py +53 -0
- tests/test_workers.py +91 -0
- tools/verify_drain.py +183 -0
- __init__.py +0 -2
- hello.py +0 -6
- iwa-0.0.0.dist-info/METADATA +0 -10
- iwa-0.0.0.dist-info/RECORD +0 -6
- iwa-0.0.0.dist-info/top_level.txt +0 -2
- {iwa-0.0.0.dist-info → iwa-0.0.1a2.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"""Lifecycle and operational flow tests for Olas ServiceManager."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock, patch
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from iwa.plugins.olas.contracts.service import ServiceState
|
|
8
|
+
from iwa.plugins.olas.contracts.staking import StakingState
|
|
9
|
+
from iwa.plugins.olas.service_manager import ServiceManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def mock_wallet():
|
|
14
|
+
"""Mock wallet for testing."""
|
|
15
|
+
wallet = MagicMock()
|
|
16
|
+
wallet.master_account.address = "0x1234567890123456789012345678901234567890"
|
|
17
|
+
wallet.key_storage.get_account.return_value.address = (
|
|
18
|
+
"0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
19
|
+
)
|
|
20
|
+
wallet.key_storage.create_account.return_value.address = (
|
|
21
|
+
"0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
|
22
|
+
)
|
|
23
|
+
wallet.sign_and_send_transaction.return_value = (True, {"status": 1})
|
|
24
|
+
wallet.send.return_value = (True, {"status": 1})
|
|
25
|
+
wallet.balance_service = MagicMock()
|
|
26
|
+
wallet.transfer_service = MagicMock()
|
|
27
|
+
# Default behavior for balance checking calls to avoid AttributeError
|
|
28
|
+
wallet.balance_service.get_erc20_balance_wei.return_value = 10**20
|
|
29
|
+
return wallet
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.fixture
|
|
33
|
+
def mock_config():
|
|
34
|
+
"""Mock config for testing."""
|
|
35
|
+
config = MagicMock()
|
|
36
|
+
olas_config = MagicMock()
|
|
37
|
+
olas_config.services = {}
|
|
38
|
+
olas_config.get_service.return_value = None
|
|
39
|
+
olas_config.get_service.return_value = None
|
|
40
|
+
config.plugins = {"olas": olas_config}
|
|
41
|
+
config.save_config = MagicMock()
|
|
42
|
+
return config
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
46
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
47
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
48
|
+
@patch("iwa.plugins.olas.service_manager.staking.ERC20Contract")
|
|
49
|
+
def test_create_service_success(
|
|
50
|
+
mock_erc20, mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet
|
|
51
|
+
):
|
|
52
|
+
"""Test successful service creation."""
|
|
53
|
+
# Setup Config with new OlasConfig structure
|
|
54
|
+
mock_config_inst = mock_config_cls.return_value
|
|
55
|
+
mock_olas_config = MagicMock()
|
|
56
|
+
mock_olas_config.services = {}
|
|
57
|
+
mock_olas_config.get_service.return_value = None
|
|
58
|
+
mock_olas_config.get_service.return_value = None
|
|
59
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
60
|
+
mock_config_inst.save_config = MagicMock()
|
|
61
|
+
|
|
62
|
+
# Setup Registry to return event
|
|
63
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
64
|
+
mock_registry_inst.extract_events.return_value = [
|
|
65
|
+
{"name": "CreateService", "args": {"serviceId": 123}}
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# Setup Manager
|
|
69
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
70
|
+
|
|
71
|
+
# Patch ChainInterfaces
|
|
72
|
+
with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_chains:
|
|
73
|
+
mock_chains.return_value.get.return_value.chain.get_token_address.return_value = None
|
|
74
|
+
|
|
75
|
+
# Call create
|
|
76
|
+
service_id = manager.create(bond_amount_wei=10)
|
|
77
|
+
|
|
78
|
+
assert service_id == 123
|
|
79
|
+
# Verify add_service was called
|
|
80
|
+
mock_olas_config.add_service.assert_called_once()
|
|
81
|
+
# Verify config was saved
|
|
82
|
+
mock_config_inst.save_config.assert_called_once()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
86
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
87
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
88
|
+
@patch("iwa.plugins.olas.service_manager.staking.ERC20Contract")
|
|
89
|
+
def test_create_service_failures(
|
|
90
|
+
mock_erc20, mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet
|
|
91
|
+
):
|
|
92
|
+
"""Test service creation failure modes."""
|
|
93
|
+
mock_config_inst = mock_config_cls.return_value
|
|
94
|
+
mock_olas_config = MagicMock()
|
|
95
|
+
mock_olas_config.get_service.return_value = None
|
|
96
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
97
|
+
|
|
98
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
99
|
+
|
|
100
|
+
# 1. Transaction fails
|
|
101
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
102
|
+
with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_chains:
|
|
103
|
+
mock_chains.return_value.get.return_value.chain.get_token_address.return_value = None
|
|
104
|
+
res = manager.create()
|
|
105
|
+
assert res is None
|
|
106
|
+
|
|
107
|
+
# Reset wallet
|
|
108
|
+
mock_wallet.sign_and_send_transaction.return_value = (True, {})
|
|
109
|
+
|
|
110
|
+
# 2. Event missing
|
|
111
|
+
mock_registry_contract.return_value.extract_events.return_value = []
|
|
112
|
+
with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_chains:
|
|
113
|
+
mock_chains.return_value.get.return_value.chain.get_token_address.return_value = None
|
|
114
|
+
res = manager.create()
|
|
115
|
+
# Should effectively return None/False depending on implementation,
|
|
116
|
+
# code says "if service_id is None: logger.error..." but proceeds to assign None
|
|
117
|
+
# and returns service_id which is None.
|
|
118
|
+
assert res is None
|
|
119
|
+
|
|
120
|
+
# 3. Approval fails
|
|
121
|
+
mock_registry_contract.return_value.extract_events.return_value = [
|
|
122
|
+
{"name": "CreateService", "args": {"serviceId": 123}}
|
|
123
|
+
]
|
|
124
|
+
# First tx (create) success, Second tx (approve) fails
|
|
125
|
+
mock_wallet.sign_and_send_transaction.reset_mock()
|
|
126
|
+
mock_wallet.sign_and_send_transaction.return_value = (
|
|
127
|
+
None # Clear return_value to let side_effect work
|
|
128
|
+
)
|
|
129
|
+
mock_wallet.sign_and_send_transaction.side_effect = [(True, {}), (False, {})]
|
|
130
|
+
mock_wallet.transfer_service = MagicMock()
|
|
131
|
+
mock_wallet.transfer_service.approve_erc20.return_value = False
|
|
132
|
+
|
|
133
|
+
with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_chains:
|
|
134
|
+
mock_chains.return_value.get.return_value.chain.get_token_address.return_value = (
|
|
135
|
+
"0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
136
|
+
)
|
|
137
|
+
res = manager.create(token_address_or_tag="0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f")
|
|
138
|
+
assert res == 123 or res is False # May succeed on create but fail on approval
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
142
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
143
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
144
|
+
@patch("iwa.plugins.olas.service_manager.staking.ERC20Contract")
|
|
145
|
+
def test_create_service_with_approval(
|
|
146
|
+
mock_erc20, mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet
|
|
147
|
+
):
|
|
148
|
+
"""Test service creation with token approval."""
|
|
149
|
+
mock_config_inst = mock_config_cls.return_value
|
|
150
|
+
mock_olas_config = MagicMock()
|
|
151
|
+
mock_olas_config.get_service.return_value = None
|
|
152
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
153
|
+
|
|
154
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
155
|
+
mock_registry_inst.extract_events.return_value = [
|
|
156
|
+
{"name": "CreateService", "args": {"serviceId": 123}}
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
160
|
+
mock_wallet.transfer_service = MagicMock()
|
|
161
|
+
mock_wallet.transfer_service.approve_erc20.return_value = True
|
|
162
|
+
|
|
163
|
+
with patch("iwa.plugins.olas.service_manager.base.ChainInterfaces") as mock_chains:
|
|
164
|
+
mock_chains.return_value.get.return_value.chain.get_token_address.return_value = (
|
|
165
|
+
"0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
166
|
+
)
|
|
167
|
+
manager.create(token_address_or_tag="0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f")
|
|
168
|
+
|
|
169
|
+
# Verify wallet transfer_service was used for approval
|
|
170
|
+
assert mock_wallet.sign_and_send_transaction.call_count >= 1
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
174
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
175
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
176
|
+
def test_activate_registration(
|
|
177
|
+
mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet
|
|
178
|
+
):
|
|
179
|
+
"""Test service registration activation."""
|
|
180
|
+
mock_config_inst = mock_config_cls.return_value
|
|
181
|
+
mock_olas_config = MagicMock()
|
|
182
|
+
mock_service = MagicMock()
|
|
183
|
+
mock_service.service_id = 123
|
|
184
|
+
mock_service.chain_name = "gnosis"
|
|
185
|
+
mock_service.token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
186
|
+
mock_olas_config.get_service.return_value = mock_service
|
|
187
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
188
|
+
|
|
189
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
190
|
+
mock_registry_inst.get_service.return_value = {
|
|
191
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
192
|
+
"security_deposit": 50000000000000000000,
|
|
193
|
+
}
|
|
194
|
+
mock_registry_inst.extract_events.return_value = [{"name": "ActivateRegistration"}]
|
|
195
|
+
|
|
196
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
197
|
+
|
|
198
|
+
# Explicitly set mock return values to ensure they aren't overridden
|
|
199
|
+
mock_wallet.balance_service.get_erc20_balance_wei.return_value = (
|
|
200
|
+
50000000000000000000 * 2
|
|
201
|
+
) # Enough balance
|
|
202
|
+
mock_wallet.transfer_service.get_erc20_allowance.return_value = (
|
|
203
|
+
50000000000000000000 * 2
|
|
204
|
+
) # Enough allowance
|
|
205
|
+
|
|
206
|
+
success = manager.activate_registration()
|
|
207
|
+
assert success is True
|
|
208
|
+
|
|
209
|
+
# Failures
|
|
210
|
+
# 1. Wrong state
|
|
211
|
+
mock_registry_inst.get_service.return_value = {
|
|
212
|
+
"state": ServiceState.DEPLOYED,
|
|
213
|
+
"security_deposit": 50000000000000000000,
|
|
214
|
+
}
|
|
215
|
+
assert manager.activate_registration() is False
|
|
216
|
+
|
|
217
|
+
# 2. Tx fail
|
|
218
|
+
mock_registry_inst.get_service.return_value = {
|
|
219
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
220
|
+
"security_deposit": 50000000000000000000,
|
|
221
|
+
}
|
|
222
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
223
|
+
assert manager.activate_registration() is False
|
|
224
|
+
|
|
225
|
+
# 3. Event missing
|
|
226
|
+
mock_wallet.sign_and_send_transaction.return_value = (True, {})
|
|
227
|
+
mock_registry_inst.extract_events.return_value = []
|
|
228
|
+
assert manager.activate_registration() is False
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
232
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
233
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
234
|
+
def test_register_agent(mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet):
|
|
235
|
+
"""Test agent registration flow."""
|
|
236
|
+
mock_config_inst = mock_config_cls.return_value
|
|
237
|
+
mock_olas_config = MagicMock()
|
|
238
|
+
mock_service = MagicMock()
|
|
239
|
+
mock_service.service_id = 123
|
|
240
|
+
mock_service.chain_name = "gnosis"
|
|
241
|
+
mock_service.token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
242
|
+
mock_olas_config.get_service.return_value = mock_service
|
|
243
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
244
|
+
|
|
245
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
246
|
+
mock_registry_inst.get_service.return_value = {
|
|
247
|
+
"state": ServiceState.ACTIVE_REGISTRATION,
|
|
248
|
+
"security_deposit": 50000000000000000000,
|
|
249
|
+
}
|
|
250
|
+
mock_registry_inst.extract_events.return_value = [{"name": "RegisterInstance"}]
|
|
251
|
+
|
|
252
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
253
|
+
|
|
254
|
+
success = manager.register_agent()
|
|
255
|
+
assert success is True
|
|
256
|
+
assert mock_olas_config.agent_address is not None
|
|
257
|
+
|
|
258
|
+
# Failures
|
|
259
|
+
# 1. Wrong state
|
|
260
|
+
mock_registry_inst.get_service.return_value = {
|
|
261
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
262
|
+
"security_deposit": 50000000000000000000,
|
|
263
|
+
}
|
|
264
|
+
assert manager.register_agent() is False
|
|
265
|
+
|
|
266
|
+
# 2. Tx fail
|
|
267
|
+
mock_registry_inst.get_service.return_value = {
|
|
268
|
+
"state": ServiceState.ACTIVE_REGISTRATION,
|
|
269
|
+
"security_deposit": 50000000000000000000,
|
|
270
|
+
}
|
|
271
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
272
|
+
assert manager.register_agent() is False
|
|
273
|
+
|
|
274
|
+
# 3. Event missing
|
|
275
|
+
mock_wallet.sign_and_send_transaction.return_value = (True, {})
|
|
276
|
+
mock_registry_inst.extract_events.return_value = []
|
|
277
|
+
assert manager.register_agent() is False
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
281
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
282
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
283
|
+
def test_deploy(mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet):
|
|
284
|
+
"""Test service deployment."""
|
|
285
|
+
# Setup mock service
|
|
286
|
+
mock_service = MagicMock()
|
|
287
|
+
mock_service.service_id = 123
|
|
288
|
+
mock_service.chain_name = "gnosis"
|
|
289
|
+
mock_service.token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
290
|
+
mock_service.multisig_address = None
|
|
291
|
+
|
|
292
|
+
mock_olas_config = MagicMock()
|
|
293
|
+
mock_olas_config.get_service.return_value = mock_service
|
|
294
|
+
|
|
295
|
+
mock_config_inst = mock_config_cls.return_value
|
|
296
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
297
|
+
mock_config_inst.save_config = MagicMock()
|
|
298
|
+
|
|
299
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
300
|
+
mock_registry_inst.get_service.return_value = {
|
|
301
|
+
"state": ServiceState.FINISHED_REGISTRATION,
|
|
302
|
+
"security_deposit": 50000000000000000000,
|
|
303
|
+
}
|
|
304
|
+
mock_registry_inst.extract_events.return_value = [
|
|
305
|
+
{"name": "DeployService"},
|
|
306
|
+
{
|
|
307
|
+
"name": "CreateMultisigWithAgents",
|
|
308
|
+
"args": {"multisig": "0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"},
|
|
309
|
+
},
|
|
310
|
+
]
|
|
311
|
+
|
|
312
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
313
|
+
|
|
314
|
+
multisig = manager.deploy()
|
|
315
|
+
assert multisig == "0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
|
|
316
|
+
mock_config_inst.save_config.assert_called()
|
|
317
|
+
|
|
318
|
+
# Failures
|
|
319
|
+
# 1. Wrong state
|
|
320
|
+
mock_registry_inst.get_service.return_value = {
|
|
321
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
322
|
+
"security_deposit": 50000000000000000000,
|
|
323
|
+
}
|
|
324
|
+
assert manager.deploy() is False # returns False or None? Code says False if state wrong
|
|
325
|
+
|
|
326
|
+
# 2. Tx fail
|
|
327
|
+
mock_registry_inst.get_service.return_value = {
|
|
328
|
+
"state": ServiceState.FINISHED_REGISTRATION,
|
|
329
|
+
"security_deposit": 50000000000000000000,
|
|
330
|
+
}
|
|
331
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
332
|
+
assert manager.deploy() is None
|
|
333
|
+
|
|
334
|
+
# 3. Event missing (DeployService)
|
|
335
|
+
mock_wallet.sign_and_send_transaction.return_value = (True, {})
|
|
336
|
+
mock_registry_inst.extract_events.return_value = []
|
|
337
|
+
assert manager.deploy() is None
|
|
338
|
+
|
|
339
|
+
# 4. Multisig Missing
|
|
340
|
+
mock_registry_inst.extract_events.return_value = [{"name": "DeployService"}]
|
|
341
|
+
assert manager.deploy() is None
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
345
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
346
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceManagerContract")
|
|
347
|
+
def test_terminate(mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet):
|
|
348
|
+
"""Test service termination."""
|
|
349
|
+
# Setup mock service
|
|
350
|
+
mock_service = MagicMock()
|
|
351
|
+
mock_service.service_id = 123
|
|
352
|
+
mock_service.chain_name = "gnosis"
|
|
353
|
+
mock_service.token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
354
|
+
mock_service.staking_contract_address = None # Not staked
|
|
355
|
+
|
|
356
|
+
mock_olas_config = MagicMock()
|
|
357
|
+
mock_olas_config.get_service.return_value = mock_service
|
|
358
|
+
|
|
359
|
+
mock_config_inst = mock_config_cls.return_value
|
|
360
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
361
|
+
mock_config_inst.save_config = MagicMock()
|
|
362
|
+
|
|
363
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
364
|
+
mock_registry_inst.get_service.return_value = {
|
|
365
|
+
"state": ServiceState.DEPLOYED,
|
|
366
|
+
"security_deposit": 50000000000000000000,
|
|
367
|
+
}
|
|
368
|
+
mock_registry_inst.extract_events.return_value = [{"name": "TerminateService"}]
|
|
369
|
+
|
|
370
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
371
|
+
|
|
372
|
+
success = manager.terminate()
|
|
373
|
+
assert success is True
|
|
374
|
+
|
|
375
|
+
# Failures
|
|
376
|
+
# 1. Wrong state
|
|
377
|
+
mock_registry_inst.get_service.return_value = {
|
|
378
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
379
|
+
"security_deposit": 50000000000000000000,
|
|
380
|
+
}
|
|
381
|
+
assert manager.terminate() is False
|
|
382
|
+
|
|
383
|
+
# 2. Staked
|
|
384
|
+
mock_registry_inst.get_service.return_value = {
|
|
385
|
+
"state": ServiceState.DEPLOYED,
|
|
386
|
+
"security_deposit": 50000000000000000000,
|
|
387
|
+
}
|
|
388
|
+
manager.service.staking_contract_address = "0xStaked"
|
|
389
|
+
assert manager.terminate() is False
|
|
390
|
+
manager.service.staking_contract_address = None
|
|
391
|
+
|
|
392
|
+
# 3. Tx fail
|
|
393
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
394
|
+
assert manager.terminate() is False
|
|
395
|
+
|
|
396
|
+
# 4. No event
|
|
397
|
+
mock_wallet.sign_and_send_transaction.return_value = (True, {})
|
|
398
|
+
mock_registry_inst.extract_events.return_value = []
|
|
399
|
+
assert manager.terminate() is False
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@patch("iwa.plugins.olas.service_manager.base.Config")
|
|
403
|
+
@patch("iwa.plugins.olas.service_manager.base.ServiceRegistryContract")
|
|
404
|
+
@patch(
|
|
405
|
+
"iwa.plugins.olas.service_manager.base.ServiceManagerContract"
|
|
406
|
+
) # MUST mock specifically here
|
|
407
|
+
@patch("iwa.plugins.olas.service_manager.staking.ERC20Contract") # For checking balance
|
|
408
|
+
def test_stake(mock_erc20, mock_sm_contract, mock_registry_contract, mock_config_cls, mock_wallet):
|
|
409
|
+
"""Test service staking."""
|
|
410
|
+
# Setup mock service
|
|
411
|
+
mock_service = MagicMock()
|
|
412
|
+
mock_service.service_id = 123
|
|
413
|
+
mock_service.chain_name = "gnosis"
|
|
414
|
+
mock_service.token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
415
|
+
mock_service.staking_contract_address = None
|
|
416
|
+
|
|
417
|
+
mock_olas_config = MagicMock()
|
|
418
|
+
mock_olas_config.get_service.return_value = mock_service
|
|
419
|
+
|
|
420
|
+
mock_config_inst = mock_config_cls.return_value
|
|
421
|
+
mock_config_inst.plugins = {"olas": mock_olas_config}
|
|
422
|
+
mock_config_inst.save_config = MagicMock()
|
|
423
|
+
|
|
424
|
+
mock_registry_inst = mock_registry_contract.return_value
|
|
425
|
+
mock_registry_inst.get_service.return_value = {
|
|
426
|
+
"state": ServiceState.DEPLOYED,
|
|
427
|
+
"security_deposit": 50000000000000000000,
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
manager = ServiceManager(mock_wallet, service_key="gnosis:123")
|
|
431
|
+
|
|
432
|
+
# Mock Staking Contract
|
|
433
|
+
mock_staking = MagicMock()
|
|
434
|
+
mock_staking.staking_token_address = "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f"
|
|
435
|
+
mock_staking.address = "0xDDdDddDdDdddDDddDDddDDDDdDdDDdDDdDDDDDDd"
|
|
436
|
+
mock_staking.get_service_ids.return_value = [] # Not full
|
|
437
|
+
mock_staking.max_num_services = 10
|
|
438
|
+
mock_staking.min_staking_deposit = 100
|
|
439
|
+
mock_staking.extract_events.return_value = [{"name": "ServiceStaked"}]
|
|
440
|
+
mock_staking.get_staking_state.return_value = StakingState.STAKED
|
|
441
|
+
mock_staking.get_requirements.return_value = {
|
|
442
|
+
"staking_token": "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f",
|
|
443
|
+
"min_staking_deposit": 50000000000000000000,
|
|
444
|
+
"num_agent_instances": 1,
|
|
445
|
+
"required_agent_bond": 50000000000000000000,
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
# Mock ERC20 balance check (100 OLAS = 100e18 wei, enough for 50 min deposit)
|
|
449
|
+
mock_erc20_inst = mock_erc20.return_value
|
|
450
|
+
mock_erc20_inst.balance_of_wei.return_value = 100000000000000000000 # 100 OLAS
|
|
451
|
+
|
|
452
|
+
success = manager.stake(mock_staking)
|
|
453
|
+
assert success is True
|
|
454
|
+
assert manager.service.staking_contract_address == "0xDDdDddDdDdddDDddDDddDDDDdDdDDdDDdDDDDDDd"
|
|
455
|
+
mock_config_inst.save_config.assert_called()
|
|
456
|
+
|
|
457
|
+
# Failures
|
|
458
|
+
# 1. State not deployed
|
|
459
|
+
mock_registry_inst.get_service.return_value = {
|
|
460
|
+
"state": ServiceState.PRE_REGISTRATION,
|
|
461
|
+
"security_deposit": 50000000000000000000,
|
|
462
|
+
}
|
|
463
|
+
assert manager.stake(mock_staking) is False
|
|
464
|
+
|
|
465
|
+
# 2. Full
|
|
466
|
+
mock_registry_inst.get_service.return_value = {
|
|
467
|
+
"state": ServiceState.DEPLOYED,
|
|
468
|
+
"security_deposit": 50000000000000000000,
|
|
469
|
+
}
|
|
470
|
+
mock_staking.get_service_ids.return_value = [0] * 10
|
|
471
|
+
assert manager.stake(mock_staking) is False
|
|
472
|
+
mock_staking.get_service_ids.return_value = []
|
|
473
|
+
|
|
474
|
+
# 3. Not enough funds
|
|
475
|
+
mock_erc20_inst.balance_of_wei.return_value = 50
|
|
476
|
+
assert manager.stake(mock_staking) is False
|
|
477
|
+
mock_erc20_inst.balance_of_wei.return_value = 200
|
|
478
|
+
|
|
479
|
+
# 4. Approve fail
|
|
480
|
+
mock_wallet.sign_and_send_transaction.return_value = (False, {})
|
|
481
|
+
assert manager.stake(mock_staking) is False
|
|
482
|
+
|
|
483
|
+
# 5. Stake fail
|
|
484
|
+
# First tx (approve) success, second (stake) fail
|
|
485
|
+
mock_wallet.sign_and_send_transaction.side_effect = [(True, {}), (False, {}), (False, {})]
|
|
486
|
+
assert manager.stake(mock_staking) is False
|
|
487
|
+
|
|
488
|
+
# 6. Event missing
|
|
489
|
+
mock_wallet.sign_and_send_transaction.side_effect = [(True, {}), (True, {}), (True, {})]
|
|
490
|
+
mock_staking.extract_events.return_value = []
|
|
491
|
+
assert manager.stake(mock_staking) is False
|
|
492
|
+
|
|
493
|
+
# 7. State check fail
|
|
494
|
+
mock_wallet.sign_and_send_transaction.side_effect = [(True, {}), (True, {}), (True, {})]
|
|
495
|
+
mock_staking.extract_events.return_value = [{"name": "ServiceStaked"}]
|
|
496
|
+
mock_staking.get_staking_state.return_value = StakingState.NOT_STAKED
|
|
497
|
+
assert manager.stake(mock_staking) is False
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Tests for Mech integration in ServiceManager."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock, patch
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from iwa.plugins.olas.constants import PAYMENT_TYPE_NATIVE
|
|
8
|
+
from iwa.plugins.olas.models import OlasConfig, Service
|
|
9
|
+
from iwa.plugins.olas.service_manager import ServiceManager
|
|
10
|
+
|
|
11
|
+
# Valid Ethereum address for testing
|
|
12
|
+
VALID_PRIORITY_MECH = "0x0000000000000000000000000000000000000001"
|
|
13
|
+
VALID_MULTISIG = "0x0000000000000000000000000000000000000002"
|
|
14
|
+
VALID_MARKETPLACE = "0x0000000000000000000000000000000000000003"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def mock_wallet():
|
|
19
|
+
"""Mock wallet fixture."""
|
|
20
|
+
wallet = MagicMock()
|
|
21
|
+
wallet.safe_service = MagicMock()
|
|
22
|
+
wallet.safe_service.execute_safe_transaction.return_value = "0xMockTxHash"
|
|
23
|
+
wallet.account_service = MagicMock()
|
|
24
|
+
return wallet
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def mock_service():
|
|
29
|
+
"""Mock Service model."""
|
|
30
|
+
service = MagicMock(spec=Service)
|
|
31
|
+
service.service_id = 1
|
|
32
|
+
service.chain_name = "gnosis"
|
|
33
|
+
service.multisig_address = VALID_MULTISIG
|
|
34
|
+
service.staking_contract_address = "0xStakingAddress"
|
|
35
|
+
return service
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.fixture
|
|
39
|
+
def mock_olas_config(mock_service):
|
|
40
|
+
"""Mock OlasConfig."""
|
|
41
|
+
config = MagicMock(spec=OlasConfig)
|
|
42
|
+
config.get_service.return_value = mock_service
|
|
43
|
+
return config
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.fixture
|
|
47
|
+
def service_manager(mock_wallet, mock_olas_config, mock_service):
|
|
48
|
+
"""Create ServiceManager with mocks."""
|
|
49
|
+
with patch("iwa.plugins.olas.service_manager.Config") as mock_config_class:
|
|
50
|
+
mock_config = mock_config_class.return_value
|
|
51
|
+
mock_config.plugins = {"olas": mock_olas_config}
|
|
52
|
+
|
|
53
|
+
sm = ServiceManager(mock_wallet, service_key="gnosis:1")
|
|
54
|
+
sm.olas_config = mock_olas_config
|
|
55
|
+
sm.service = mock_service
|
|
56
|
+
# Mocking registry to avoid initialization calls
|
|
57
|
+
sm.registry = MagicMock()
|
|
58
|
+
sm.registry.chain_interface = MagicMock()
|
|
59
|
+
sm.registry.chain_interface.web3 = MagicMock()
|
|
60
|
+
sm.chain_interface = MagicMock()
|
|
61
|
+
sm.chain_interface.chain.name = "gnosis"
|
|
62
|
+
sm.chain_name = "gnosis"
|
|
63
|
+
return sm
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TestServiceManagerMech:
|
|
67
|
+
"""Tests for Mech request functionality in ServiceManager."""
|
|
68
|
+
|
|
69
|
+
def test_send_mech_request_marketplace_requires_priority_mech(self, service_manager):
|
|
70
|
+
"""Test that marketplace request requires priority_mech."""
|
|
71
|
+
data = b"marketplace data"
|
|
72
|
+
|
|
73
|
+
with patch(
|
|
74
|
+
"iwa.plugins.olas.service_manager.mech.MechMarketplaceContract"
|
|
75
|
+
) as mock_market_class:
|
|
76
|
+
mock_market = mock_market_class.return_value
|
|
77
|
+
mock_market.prepare_request_tx.return_value = {
|
|
78
|
+
"data": "0xMarketplaceEncoded",
|
|
79
|
+
"value": 2 * 10**16,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Should return None because priority_mech is not provided
|
|
83
|
+
tx_hash = service_manager.send_mech_request(
|
|
84
|
+
data=data,
|
|
85
|
+
use_marketplace=True,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
assert tx_hash is None
|
|
89
|
+
|
|
90
|
+
def test_send_mech_request_marketplace(self, service_manager, mock_wallet):
|
|
91
|
+
"""Test sending a marketplace Mech request."""
|
|
92
|
+
data = b"marketplace data"
|
|
93
|
+
payment_type_bytes = bytes.fromhex(PAYMENT_TYPE_NATIVE)
|
|
94
|
+
value = 2 * 10**16
|
|
95
|
+
|
|
96
|
+
# Mock the account resolution to return a Safe account
|
|
97
|
+
from iwa.core.models import StoredSafeAccount
|
|
98
|
+
|
|
99
|
+
mock_safe_account = MagicMock(spec=StoredSafeAccount)
|
|
100
|
+
mock_wallet.account_service.resolve_account.return_value = mock_safe_account
|
|
101
|
+
|
|
102
|
+
with patch(
|
|
103
|
+
"iwa.plugins.olas.service_manager.mech.MechMarketplaceContract"
|
|
104
|
+
) as mock_market_class:
|
|
105
|
+
mock_market = mock_market_class.return_value
|
|
106
|
+
mock_market.prepare_request_tx.return_value = {
|
|
107
|
+
"data": "0xMarketplaceEncoded",
|
|
108
|
+
"value": value,
|
|
109
|
+
}
|
|
110
|
+
# Mock event extraction to simulate successful event
|
|
111
|
+
mock_market.extract_events.return_value = [{"name": "MarketplaceRequest"}]
|
|
112
|
+
|
|
113
|
+
# Mock wait_for_transaction_receipt
|
|
114
|
+
service_manager.registry.chain_interface.web3.eth.wait_for_transaction_receipt.return_value = {}
|
|
115
|
+
|
|
116
|
+
tx_hash = service_manager.send_mech_request(
|
|
117
|
+
data=data,
|
|
118
|
+
use_marketplace=True,
|
|
119
|
+
priority_mech=VALID_PRIORITY_MECH,
|
|
120
|
+
response_timeout=300, # Within bounds [60, 300]
|
|
121
|
+
value=value,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
assert tx_hash == "0xMockTxHash"
|
|
125
|
+
# Note: max_delivery_rate now defaults to value
|
|
126
|
+
mock_market.prepare_request_tx.assert_called_once_with(
|
|
127
|
+
from_address=VALID_MULTISIG,
|
|
128
|
+
request_data=data,
|
|
129
|
+
priority_mech=VALID_PRIORITY_MECH,
|
|
130
|
+
response_timeout=300,
|
|
131
|
+
max_delivery_rate=value, # Defaults to value
|
|
132
|
+
payment_type=payment_type_bytes,
|
|
133
|
+
payment_data=b"",
|
|
134
|
+
value=value,
|
|
135
|
+
)
|