olas-operate-middleware 0.10.19__py3-none-any.whl → 0.11.0__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.
- {olas_operate_middleware-0.10.19.dist-info → olas_operate_middleware-0.11.0.dist-info}/METADATA +3 -1
- {olas_operate_middleware-0.10.19.dist-info → olas_operate_middleware-0.11.0.dist-info}/RECORD +30 -27
- operate/bridge/bridge_manager.py +10 -12
- operate/bridge/providers/lifi_provider.py +5 -4
- operate/bridge/providers/native_bridge_provider.py +6 -5
- operate/bridge/providers/provider.py +22 -87
- operate/bridge/providers/relay_provider.py +5 -4
- operate/cli.py +446 -168
- operate/constants.py +22 -2
- operate/keys.py +13 -0
- operate/ledger/__init__.py +107 -2
- operate/ledger/profiles.py +79 -11
- operate/operate_types.py +205 -2
- operate/quickstart/run_service.py +6 -10
- operate/services/agent_runner.py +5 -3
- operate/services/deployment_runner.py +3 -0
- operate/services/funding_manager.py +904 -0
- operate/services/health_checker.py +4 -4
- operate/services/manage.py +183 -310
- operate/services/protocol.py +392 -140
- operate/services/service.py +81 -5
- operate/settings.py +70 -0
- operate/utils/__init__.py +0 -29
- operate/utils/gnosis.py +79 -24
- operate/utils/single_instance.py +226 -0
- operate/wallet/master.py +221 -181
- operate/wallet/wallet_recovery_manager.py +5 -5
- {olas_operate_middleware-0.10.19.dist-info → olas_operate_middleware-0.11.0.dist-info}/WHEEL +0 -0
- {olas_operate_middleware-0.10.19.dist-info → olas_operate_middleware-0.11.0.dist-info}/entry_points.txt +0 -0
- {olas_operate_middleware-0.10.19.dist-info → olas_operate_middleware-0.11.0.dist-info}/licenses/LICENSE +0 -0
operate/services/manage.py
CHANGED
|
@@ -19,18 +19,15 @@
|
|
|
19
19
|
# ------------------------------------------------------------------------------
|
|
20
20
|
"""Service manager."""
|
|
21
21
|
|
|
22
|
-
import asyncio
|
|
23
22
|
import json
|
|
24
23
|
import logging
|
|
25
24
|
import os
|
|
26
25
|
import traceback
|
|
27
26
|
import typing as t
|
|
28
27
|
from collections import Counter, defaultdict
|
|
29
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
30
28
|
from contextlib import suppress
|
|
31
29
|
from http import HTTPStatus
|
|
32
30
|
from pathlib import Path
|
|
33
|
-
from time import time
|
|
34
31
|
|
|
35
32
|
import requests
|
|
36
33
|
from aea.helpers.base import IPFSHash
|
|
@@ -38,14 +35,16 @@ from aea_ledger_ethereum import LedgerApi
|
|
|
38
35
|
from autonomy.chain.base import registry_contracts
|
|
39
36
|
from autonomy.chain.config import CHAIN_PROFILES, ChainType
|
|
40
37
|
from autonomy.chain.metadata import IPFS_URI_PREFIX
|
|
41
|
-
from web3 import Web3
|
|
42
38
|
|
|
43
39
|
from operate.constants import (
|
|
44
40
|
AGENT_LOG_DIR,
|
|
45
41
|
AGENT_LOG_ENV_VAR,
|
|
46
42
|
AGENT_PERSISTENT_STORAGE_DIR,
|
|
47
43
|
AGENT_PERSISTENT_STORAGE_ENV_VAR,
|
|
44
|
+
DEFAULT_TOPUP_THRESHOLD,
|
|
48
45
|
IPFS_ADDRESS,
|
|
46
|
+
MIN_AGENT_BOND,
|
|
47
|
+
MIN_SECURITY_DEPOSIT,
|
|
49
48
|
ZERO_ADDRESS,
|
|
50
49
|
)
|
|
51
50
|
from operate.data import DATA_DIR
|
|
@@ -53,21 +52,20 @@ from operate.data.contracts.mech_activity.contract import MechActivityContract
|
|
|
53
52
|
from operate.data.contracts.requester_activity_checker.contract import (
|
|
54
53
|
RequesterActivityCheckerContract,
|
|
55
54
|
)
|
|
56
|
-
from operate.data.contracts.staking_token.contract import StakingTokenContract
|
|
57
55
|
from operate.keys import KeysManager
|
|
58
|
-
from operate.ledger import
|
|
56
|
+
from operate.ledger import get_default_rpc
|
|
59
57
|
from operate.ledger.profiles import (
|
|
60
58
|
CONTRACTS,
|
|
61
|
-
|
|
59
|
+
DEFAULT_EOA_THRESHOLD,
|
|
60
|
+
DEFAULT_EOA_TOPUPS,
|
|
62
61
|
DEFAULT_PRIORITY_MECH,
|
|
63
62
|
OLAS,
|
|
64
|
-
STAKING,
|
|
65
|
-
USDC,
|
|
66
63
|
WRAPPED_NATIVE_ASSET,
|
|
67
64
|
get_staking_contract,
|
|
68
65
|
)
|
|
69
66
|
from operate.operate_types import (
|
|
70
67
|
Chain,
|
|
68
|
+
ChainAmounts,
|
|
71
69
|
FundingValues,
|
|
72
70
|
LedgerConfig,
|
|
73
71
|
MechMarketplaceConfig,
|
|
@@ -75,7 +73,13 @@ from operate.operate_types import (
|
|
|
75
73
|
ServiceEnvProvisionType,
|
|
76
74
|
ServiceTemplate,
|
|
77
75
|
)
|
|
78
|
-
from operate.services.
|
|
76
|
+
from operate.services.funding_manager import FundingManager
|
|
77
|
+
from operate.services.protocol import (
|
|
78
|
+
EthSafeTxBuilder,
|
|
79
|
+
OnChainManager,
|
|
80
|
+
StakingManager,
|
|
81
|
+
StakingState,
|
|
82
|
+
)
|
|
79
83
|
from operate.services.service import (
|
|
80
84
|
ChainConfig,
|
|
81
85
|
Deployment,
|
|
@@ -87,14 +91,16 @@ from operate.services.service import (
|
|
|
87
91
|
Service,
|
|
88
92
|
)
|
|
89
93
|
from operate.services.utils.mech import deploy_mech
|
|
90
|
-
from operate.utils.gnosis import
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
from operate.utils.gnosis import (
|
|
95
|
+
get_asset_balance,
|
|
96
|
+
get_assets_balances,
|
|
97
|
+
transfer_erc20_from_safe,
|
|
98
|
+
)
|
|
99
|
+
from operate.wallet.master import InsufficientFundsException, MasterWalletManager
|
|
94
100
|
|
|
95
101
|
|
|
96
102
|
# pylint: disable=redefined-builtin
|
|
97
|
-
|
|
103
|
+
|
|
98
104
|
# At the moment, we only support running one agent per service locally on a machine.
|
|
99
105
|
# If multiple agents are provided in the service.yaml file, only the 0th index config will be used.
|
|
100
106
|
NUM_LOCAL_AGENT_INSTANCES = 1
|
|
@@ -107,6 +113,7 @@ class ServiceManager:
|
|
|
107
113
|
self,
|
|
108
114
|
path: Path,
|
|
109
115
|
wallet_manager: MasterWalletManager,
|
|
116
|
+
funding_manager: FundingManager,
|
|
110
117
|
logger: logging.Logger,
|
|
111
118
|
skip_dependency_check: t.Optional[bool] = False,
|
|
112
119
|
) -> None:
|
|
@@ -121,6 +128,7 @@ class ServiceManager:
|
|
|
121
128
|
self.path = path
|
|
122
129
|
self.keys_manager = KeysManager()
|
|
123
130
|
self.wallet_manager = wallet_manager
|
|
131
|
+
self.funding_manager = funding_manager
|
|
124
132
|
self.logger = logger
|
|
125
133
|
self.skip_depencency_check = skip_dependency_check
|
|
126
134
|
|
|
@@ -415,18 +423,26 @@ class ServiceManager:
|
|
|
415
423
|
and (
|
|
416
424
|
on_chain_hash != service.hash
|
|
417
425
|
or current_agent_id != staking_params["agent_ids"][0]
|
|
418
|
-
or
|
|
426
|
+
or (
|
|
427
|
+
user_params.use_staking
|
|
428
|
+
and current_agent_bond != staking_params["min_staking_deposit"]
|
|
429
|
+
)
|
|
430
|
+
# TODO Missing complete this check for non-staked services it should compare the current_agent_bond from the protocol, now it's only read for the staking contract.
|
|
419
431
|
or on_chain_description != service.description
|
|
420
432
|
)
|
|
421
433
|
)
|
|
422
434
|
current_staking_program = self._get_current_staking_program(service, chain)
|
|
423
435
|
|
|
436
|
+
self.logger.info(f"{chain_data.token=}")
|
|
437
|
+
self.logger.info(f"{user_params.use_staking=}")
|
|
424
438
|
self.logger.info(f"{current_staking_program=}")
|
|
425
439
|
self.logger.info(f"{user_params.staking_program_id=}")
|
|
426
440
|
self.logger.info(f"{on_chain_hash=}")
|
|
427
441
|
self.logger.info(f"{service.hash=}")
|
|
428
442
|
self.logger.info(f"{current_agent_id=}")
|
|
429
|
-
self.logger.info(f"{staking_params['agent_ids']
|
|
443
|
+
self.logger.info(f"{staking_params['agent_ids']=}")
|
|
444
|
+
self.logger.info(f"{current_agent_bond=}")
|
|
445
|
+
self.logger.info(f"{staking_params['min_staking_deposit']=}")
|
|
430
446
|
self.logger.info(f"{is_first_mint=}")
|
|
431
447
|
self.logger.info(f"{is_update=}")
|
|
432
448
|
|
|
@@ -595,7 +611,7 @@ class ServiceManager:
|
|
|
595
611
|
]
|
|
596
612
|
|
|
597
613
|
except Exception as e: # pylint: disable=broad-except
|
|
598
|
-
self.logger.
|
|
614
|
+
self.logger.debug(f"{e}: {traceback.format_exc()}")
|
|
599
615
|
self.logger.warning(
|
|
600
616
|
"Cannot determine type of activity checker contract. Using default parameters. "
|
|
601
617
|
"NOTE: This will be an exception in the future!"
|
|
@@ -815,7 +831,12 @@ class ServiceManager:
|
|
|
815
831
|
# on_chain_hash != service.hash or # noqa
|
|
816
832
|
current_agent_id != target_staking_params["agent_ids"][0]
|
|
817
833
|
# TODO This has to be removed for Optimus (needs to be properly implemented). Needs to be put back for Trader!
|
|
818
|
-
or
|
|
834
|
+
or (
|
|
835
|
+
user_params.use_staking
|
|
836
|
+
and current_agent_bond
|
|
837
|
+
!= target_staking_params["min_staking_deposit"]
|
|
838
|
+
)
|
|
839
|
+
# TODO Missing complete this check for non-staked services it should compare the current_agent_bond from the protocol, now it's only read for the staking contract.
|
|
819
840
|
or current_staking_params["staking_token"]
|
|
820
841
|
!= target_staking_params["staking_token"]
|
|
821
842
|
or on_chain_description != service.description
|
|
@@ -823,12 +844,13 @@ class ServiceManager:
|
|
|
823
844
|
)
|
|
824
845
|
|
|
825
846
|
self.logger.info(f"{chain_data.token=}")
|
|
847
|
+
self.logger.info(f"{user_params.use_staking=}")
|
|
826
848
|
self.logger.info(f"{current_staking_program=}")
|
|
827
849
|
self.logger.info(f"{user_params.staking_program_id=}")
|
|
828
850
|
self.logger.info(f"{on_chain_hash=}")
|
|
829
851
|
self.logger.info(f"{service.hash=}")
|
|
830
852
|
self.logger.info(f"{current_agent_id=}")
|
|
831
|
-
self.logger.info(f"{target_staking_params['agent_ids']
|
|
853
|
+
self.logger.info(f"{target_staking_params['agent_ids']=}")
|
|
832
854
|
self.logger.info(f"{current_agent_bond=}")
|
|
833
855
|
self.logger.info(f"{target_staking_params['min_staking_deposit']=}")
|
|
834
856
|
self.logger.info(f"{is_first_mint=}")
|
|
@@ -941,7 +963,6 @@ class ServiceManager:
|
|
|
941
963
|
self._get_on_chain_state(service=service, chain=chain)
|
|
942
964
|
== OnChainState.PRE_REGISTRATION
|
|
943
965
|
):
|
|
944
|
-
# TODO Verify that this is incorrect: cost_of_bond = staking_params["min_staking_deposit"]
|
|
945
966
|
cost_of_bond = user_params.cost_of_bond
|
|
946
967
|
if user_params.use_staking:
|
|
947
968
|
token_utility = target_staking_params["service_registry_token_utility"]
|
|
@@ -978,7 +999,7 @@ class ServiceManager:
|
|
|
978
999
|
self.logger.info(
|
|
979
1000
|
f"Approved {token_utility_allowance} OLAS from {safe} to {token_utility}"
|
|
980
1001
|
)
|
|
981
|
-
cost_of_bond =
|
|
1002
|
+
cost_of_bond = MIN_AGENT_BOND
|
|
982
1003
|
|
|
983
1004
|
self.logger.info("Activating service")
|
|
984
1005
|
|
|
@@ -988,7 +1009,9 @@ class ServiceManager:
|
|
|
988
1009
|
address=safe,
|
|
989
1010
|
)
|
|
990
1011
|
|
|
991
|
-
if
|
|
1012
|
+
if (
|
|
1013
|
+
native_balance < cost_of_bond
|
|
1014
|
+
): # TODO check that this is the security deposit
|
|
992
1015
|
message = f"Cannot activate service: address {safe} {native_balance=} < {cost_of_bond=}."
|
|
993
1016
|
self.logger.error(message)
|
|
994
1017
|
raise ValueError(message)
|
|
@@ -1040,7 +1063,7 @@ class ServiceManager:
|
|
|
1040
1063
|
self.logger.info(
|
|
1041
1064
|
f"Approved {token_utility_allowance} OLAS from {safe} to {token_utility}"
|
|
1042
1065
|
)
|
|
1043
|
-
cost_of_bond =
|
|
1066
|
+
cost_of_bond = MIN_AGENT_BOND
|
|
1044
1067
|
|
|
1045
1068
|
self.logger.info(
|
|
1046
1069
|
f"Registering agent instances: {chain_data.token} -> {service.agent_addresses}"
|
|
@@ -1052,7 +1075,7 @@ class ServiceManager:
|
|
|
1052
1075
|
address=safe,
|
|
1053
1076
|
)
|
|
1054
1077
|
|
|
1055
|
-
if native_balance < cost_of_bond:
|
|
1078
|
+
if native_balance < cost_of_bond * len(service.agent_addresses):
|
|
1056
1079
|
message = f"Cannot register agent instances: address {safe} {native_balance=} < {cost_of_bond=}."
|
|
1057
1080
|
self.logger.error(message)
|
|
1058
1081
|
raise ValueError(message)
|
|
@@ -1067,27 +1090,21 @@ class ServiceManager:
|
|
|
1067
1090
|
).settle()
|
|
1068
1091
|
|
|
1069
1092
|
# Deploy service
|
|
1093
|
+
is_initial_funding = False
|
|
1070
1094
|
if (
|
|
1071
1095
|
self._get_on_chain_state(service=service, chain=chain)
|
|
1072
1096
|
== OnChainState.FINISHED_REGISTRATION
|
|
1073
1097
|
):
|
|
1074
1098
|
self.logger.info("Deploying service")
|
|
1075
1099
|
|
|
1076
|
-
reuse_multisig = True
|
|
1077
1100
|
info = sftxb.info(token_id=chain_data.token)
|
|
1078
1101
|
service_safe_address = info["multisig"]
|
|
1079
1102
|
if service_safe_address == ZERO_ADDRESS:
|
|
1080
1103
|
reuse_multisig = False
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
True # Ensure is true for non-deployed multisigs
|
|
1086
|
-
)
|
|
1087
|
-
if (
|
|
1088
|
-
service_safe_address is not None
|
|
1089
|
-
and service_safe_address != ZERO_ADDRESS
|
|
1090
|
-
):
|
|
1104
|
+
is_initial_funding = True
|
|
1105
|
+
is_recovery_module_enabled = True
|
|
1106
|
+
else:
|
|
1107
|
+
reuse_multisig = True
|
|
1091
1108
|
is_recovery_module_enabled = (
|
|
1092
1109
|
registry_contracts.gnosis_safe.is_module_enabled(
|
|
1093
1110
|
ledger_api=sftxb.ledger_api,
|
|
@@ -1096,6 +1113,7 @@ class ServiceManager:
|
|
|
1096
1113
|
).get("enabled")
|
|
1097
1114
|
)
|
|
1098
1115
|
|
|
1116
|
+
self.logger.info(f"{reuse_multisig=}")
|
|
1099
1117
|
self.logger.info(f"{is_recovery_module_enabled=}")
|
|
1100
1118
|
|
|
1101
1119
|
messages = sftxb.get_deploy_data_from_safe(
|
|
@@ -1114,6 +1132,9 @@ class ServiceManager:
|
|
|
1114
1132
|
chain_data.instances = info["instances"]
|
|
1115
1133
|
chain_data.multisig = info["multisig"]
|
|
1116
1134
|
|
|
1135
|
+
if is_initial_funding:
|
|
1136
|
+
self.funding_manager.fund_service_initial(service)
|
|
1137
|
+
|
|
1117
1138
|
# TODO: yet another agent specific logic for mech, which should be abstracted
|
|
1118
1139
|
if all(
|
|
1119
1140
|
var in service.env_variables
|
|
@@ -1225,7 +1246,6 @@ class ServiceManager:
|
|
|
1225
1246
|
self,
|
|
1226
1247
|
service_config_id: str,
|
|
1227
1248
|
chain: str,
|
|
1228
|
-
withdrawal_address: t.Optional[str] = None,
|
|
1229
1249
|
) -> None:
|
|
1230
1250
|
"""Terminate service on-chain"""
|
|
1231
1251
|
|
|
@@ -1235,10 +1255,7 @@ class ServiceManager:
|
|
|
1235
1255
|
ledger_config = chain_config.ledger_config
|
|
1236
1256
|
chain_data = chain_config.chain_data
|
|
1237
1257
|
wallet = self.wallet_manager.load(ledger_config.chain.ledger_type)
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
if withdrawal_address:
|
|
1241
|
-
withdrawal_address = Web3.to_checksum_address(withdrawal_address)
|
|
1258
|
+
master_safe = wallet.safes[Chain(chain)] # type: ignore
|
|
1242
1259
|
|
|
1243
1260
|
# TODO fixme
|
|
1244
1261
|
os.environ["CUSTOM_CHAIN_RPC"] = ledger_config.rpc
|
|
@@ -1263,23 +1280,23 @@ class ServiceManager:
|
|
|
1263
1280
|
)
|
|
1264
1281
|
|
|
1265
1282
|
# Cannot unstake, terminate flow.
|
|
1266
|
-
if is_staked and not can_unstake
|
|
1283
|
+
if is_staked and not can_unstake:
|
|
1267
1284
|
self.logger.info("Service cannot be terminated on-chain: cannot unstake.")
|
|
1268
1285
|
return
|
|
1269
|
-
|
|
1270
1286
|
# Unstake the service if applies
|
|
1271
|
-
if is_staked and
|
|
1287
|
+
if is_staked and can_unstake:
|
|
1272
1288
|
self.unstake_service_on_chain_from_safe(
|
|
1273
1289
|
service_config_id=service_config_id,
|
|
1274
1290
|
chain=chain,
|
|
1275
1291
|
staking_program_id=current_staking_program,
|
|
1276
1292
|
)
|
|
1293
|
+
# At least claim the rewards if we cannot unstake yet
|
|
1277
1294
|
elif is_staked:
|
|
1278
|
-
# at least claim the rewards if we cannot unstake yet
|
|
1279
1295
|
self.claim_on_chain_from_safe(
|
|
1280
1296
|
service_config_id=service_config_id,
|
|
1281
1297
|
chain=chain,
|
|
1282
1298
|
)
|
|
1299
|
+
return
|
|
1283
1300
|
|
|
1284
1301
|
if self._get_on_chain_state(service=service, chain=chain) in (
|
|
1285
1302
|
OnChainState.ACTIVE_REGISTRATION,
|
|
@@ -1309,38 +1326,58 @@ class ServiceManager:
|
|
|
1309
1326
|
counter_current_safe_owners = Counter(s.lower() for s in current_safe_owners)
|
|
1310
1327
|
counter_instances = Counter(s.lower() for s in service.agent_addresses)
|
|
1311
1328
|
|
|
1312
|
-
if withdrawal_address is not None:
|
|
1313
|
-
# we don't drain signer yet, because the owner swapping tx may need to happen
|
|
1314
|
-
self.drain_service_safe(
|
|
1315
|
-
service_config_id=service_config_id,
|
|
1316
|
-
withdrawal_address=withdrawal_address,
|
|
1317
|
-
chain=Chain(chain),
|
|
1318
|
-
)
|
|
1319
|
-
|
|
1320
1329
|
if counter_current_safe_owners == counter_instances:
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
"topup": chain_data.user_params.fund_requirements[
|
|
1329
|
-
ZERO_ADDRESS
|
|
1330
|
-
].agent,
|
|
1331
|
-
"threshold": chain_data.user_params.fund_requirements[
|
|
1332
|
-
ZERO_ADDRESS
|
|
1333
|
-
].agent,
|
|
1334
|
-
},
|
|
1335
|
-
"safe": {"topup": 0, "threshold": 0},
|
|
1330
|
+
requirements = ChainAmounts(
|
|
1331
|
+
{
|
|
1332
|
+
chain: {
|
|
1333
|
+
current_safe_owners[0]: {
|
|
1334
|
+
ZERO_ADDRESS: chain_data.user_params.fund_requirements[
|
|
1335
|
+
ZERO_ADDRESS
|
|
1336
|
+
].agent
|
|
1336
1337
|
}
|
|
1337
|
-
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
)
|
|
1341
|
+
balances = ChainAmounts(
|
|
1342
|
+
{
|
|
1343
|
+
chain: {
|
|
1344
|
+
current_safe_owners[0]: {
|
|
1345
|
+
ZERO_ADDRESS: get_asset_balance(
|
|
1346
|
+
ledger_api=sftxb.ledger_api,
|
|
1347
|
+
asset_address=ZERO_ADDRESS,
|
|
1348
|
+
address=service.agent_addresses[0],
|
|
1349
|
+
)
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
)
|
|
1354
|
+
if balances < requirements * DEFAULT_EOA_THRESHOLD:
|
|
1355
|
+
self.logger.info("[SERVICE MANAGER] Funding agent EOA for Safe swap.")
|
|
1356
|
+
shortfalls = ChainAmounts.shortfalls(
|
|
1357
|
+
requirements=requirements, balances=balances
|
|
1338
1358
|
)
|
|
1359
|
+
try:
|
|
1360
|
+
self.funding_manager.fund_chain_amounts(shortfalls)
|
|
1361
|
+
except InsufficientFundsException as e:
|
|
1362
|
+
recovery_module_address = CONTRACTS[Chain(chain)]["recovery_module"]
|
|
1363
|
+
is_recovery_module_enabled = (
|
|
1364
|
+
registry_contracts.gnosis_safe.is_module_enabled(
|
|
1365
|
+
ledger_api=sftxb.ledger_api,
|
|
1366
|
+
contract_address=chain_data.multisig,
|
|
1367
|
+
module_address=recovery_module_address,
|
|
1368
|
+
).get("enabled")
|
|
1369
|
+
)
|
|
1370
|
+
if is_recovery_module_enabled:
|
|
1371
|
+
self.logger.info(
|
|
1372
|
+
"[SERVICE MANAGER] Could not fund Agent EOA for service swap, but recovery module is enabled."
|
|
1373
|
+
)
|
|
1374
|
+
return
|
|
1375
|
+
raise e
|
|
1339
1376
|
|
|
1340
1377
|
self._enable_recovery_module(
|
|
1341
1378
|
service_config_id=service_config_id, chain=chain
|
|
1342
1379
|
)
|
|
1343
|
-
self.logger.info("Swapping Safe owners")
|
|
1380
|
+
self.logger.info("[SERVICE MANAGER] Swapping Safe owners")
|
|
1344
1381
|
owner_crypto = self.keys_manager.get_crypto_instance(
|
|
1345
1382
|
address=current_safe_owners[0]
|
|
1346
1383
|
)
|
|
@@ -1349,25 +1386,10 @@ class ServiceManager:
|
|
|
1349
1386
|
multisig=chain_data.multisig, # TODO this can be read from the registry
|
|
1350
1387
|
owner_cryptos=[owner_crypto], # TODO allow multiple owners
|
|
1351
1388
|
new_owner_address=(
|
|
1352
|
-
|
|
1389
|
+
master_safe if master_safe else wallet.crypto.address
|
|
1353
1390
|
), # TODO it should always be safe address
|
|
1354
1391
|
)
|
|
1355
1392
|
|
|
1356
|
-
if withdrawal_address is not None:
|
|
1357
|
-
ethereum_crypto = KeysManager().get_crypto_instance(
|
|
1358
|
-
service.agent_addresses[0]
|
|
1359
|
-
)
|
|
1360
|
-
# drain all native tokens from service signer key
|
|
1361
|
-
drain_eoa(
|
|
1362
|
-
ledger_api=self.wallet_manager.load(
|
|
1363
|
-
ledger_config.chain.ledger_type
|
|
1364
|
-
).ledger_api(chain=ledger_config.chain, rpc=ledger_config.rpc),
|
|
1365
|
-
crypto=ethereum_crypto,
|
|
1366
|
-
withdrawal_address=withdrawal_address,
|
|
1367
|
-
chain_id=ledger_config.chain.id,
|
|
1368
|
-
)
|
|
1369
|
-
self.logger.info(f"{service.name} signer drained")
|
|
1370
|
-
|
|
1371
1393
|
def _execute_recovery_module_flow_from_safe( # pylint: disable=too-many-locals
|
|
1372
1394
|
self,
|
|
1373
1395
|
service_config_id: str,
|
|
@@ -1510,82 +1532,14 @@ class ServiceManager:
|
|
|
1510
1532
|
f"Cannot enable recovery module. Safe {service_safe_address} has inconsistent owners."
|
|
1511
1533
|
)
|
|
1512
1534
|
|
|
1513
|
-
def _get_current_staking_program(
|
|
1535
|
+
def _get_current_staking_program( # pylint: disable=no-self-use
|
|
1514
1536
|
self, service: Service, chain: str
|
|
1515
1537
|
) -> t.Optional[str]:
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
service_id = chain_config.chain_data.token
|
|
1520
|
-
ledger_api = sftxb.ledger_api
|
|
1521
|
-
|
|
1522
|
-
if service_id == NON_EXISTENT_TOKEN:
|
|
1523
|
-
return None
|
|
1524
|
-
|
|
1525
|
-
service_registry = registry_contracts.service_registry.get_instance(
|
|
1526
|
-
ledger_api=ledger_api,
|
|
1527
|
-
contract_address=CONTRACTS[ledger_config.chain]["service_registry"],
|
|
1538
|
+
staking_manager = StakingManager(Chain(chain))
|
|
1539
|
+
return staking_manager.get_current_staking_program(
|
|
1540
|
+
service_id=service.chain_configs[chain].chain_data.token
|
|
1528
1541
|
)
|
|
1529
1542
|
|
|
1530
|
-
service_owner = service_registry.functions.ownerOf(service_id).call()
|
|
1531
|
-
|
|
1532
|
-
# TODO Implement in Staking Manager. Implemented here for performance issues.
|
|
1533
|
-
staking_ctr = t.cast(
|
|
1534
|
-
StakingTokenContract,
|
|
1535
|
-
StakingTokenContract.from_dir(
|
|
1536
|
-
directory=str(DATA_DIR / "contracts" / "staking_token")
|
|
1537
|
-
),
|
|
1538
|
-
)
|
|
1539
|
-
|
|
1540
|
-
try:
|
|
1541
|
-
state = StakingState(
|
|
1542
|
-
staking_ctr.get_instance(
|
|
1543
|
-
ledger_api=ledger_api,
|
|
1544
|
-
contract_address=service_owner,
|
|
1545
|
-
)
|
|
1546
|
-
.functions.getStakingState(service_id)
|
|
1547
|
-
.call()
|
|
1548
|
-
)
|
|
1549
|
-
except Exception: # pylint: disable=broad-except
|
|
1550
|
-
# Service owner is not a staking contract
|
|
1551
|
-
|
|
1552
|
-
# TODO The exception caught here should be ContractLogicError.
|
|
1553
|
-
# This exception is typically raised when the contract reverts with
|
|
1554
|
-
# a reason string. However, in some cases, the error message
|
|
1555
|
-
# does not contain a reason string, which means web3.py raises
|
|
1556
|
-
# a generic ValueError instead. It should be properly analyzed
|
|
1557
|
-
# what exceptions might be raised by web3.py in this case. To
|
|
1558
|
-
# avoid any issues we are simply catching all exceptions.
|
|
1559
|
-
return None
|
|
1560
|
-
|
|
1561
|
-
if state == StakingState.UNSTAKED:
|
|
1562
|
-
return None
|
|
1563
|
-
|
|
1564
|
-
for staking_program_id, val in STAKING[ledger_config.chain].items():
|
|
1565
|
-
if val == service_owner:
|
|
1566
|
-
return staking_program_id
|
|
1567
|
-
|
|
1568
|
-
# Fallback, if not possible to determine staking_program_id it means it's an "inner" staking contract
|
|
1569
|
-
# (e.g., in the case of DualStakingToken). Loop trough all the known contracts.
|
|
1570
|
-
for staking_program_id, staking_program_address in STAKING[
|
|
1571
|
-
ledger_config.chain
|
|
1572
|
-
].items():
|
|
1573
|
-
state = StakingState(
|
|
1574
|
-
staking_ctr.get_instance(
|
|
1575
|
-
ledger_api=ledger_api,
|
|
1576
|
-
contract_address=staking_program_address,
|
|
1577
|
-
)
|
|
1578
|
-
.functions.getStakingState(service_id)
|
|
1579
|
-
.call()
|
|
1580
|
-
)
|
|
1581
|
-
|
|
1582
|
-
if state in (StakingState.STAKED, StakingState.EVICTED):
|
|
1583
|
-
return staking_program_id
|
|
1584
|
-
|
|
1585
|
-
# it's staked, but we don't know which staking program
|
|
1586
|
-
# so the staking_program_id should be an arbitrary staking contract
|
|
1587
|
-
return service_owner
|
|
1588
|
-
|
|
1589
1543
|
def unbond_service_on_chain(
|
|
1590
1544
|
self, service_config_id: str, chain: t.Optional[str] = None
|
|
1591
1545
|
) -> None:
|
|
@@ -1892,6 +1846,16 @@ class ServiceManager:
|
|
|
1892
1846
|
)
|
|
1893
1847
|
).settle()
|
|
1894
1848
|
|
|
1849
|
+
def claim_all_on_chain_from_safe(self) -> None:
|
|
1850
|
+
"""Claim rewards from all services and chains"""
|
|
1851
|
+
self.logger.info("claim_all_on_chain_from_safe")
|
|
1852
|
+
services, _ = self.get_all_services()
|
|
1853
|
+
for service in services:
|
|
1854
|
+
self.claim_on_chain_from_safe(
|
|
1855
|
+
service_config_id=service.service_config_id,
|
|
1856
|
+
chain=service.home_chain,
|
|
1857
|
+
)
|
|
1858
|
+
|
|
1895
1859
|
def claim_on_chain_from_safe(
|
|
1896
1860
|
self,
|
|
1897
1861
|
service_config_id: str,
|
|
@@ -1904,6 +1868,14 @@ class ServiceManager:
|
|
|
1904
1868
|
ledger_config = chain_config.ledger_config
|
|
1905
1869
|
wallet = self.wallet_manager.load(ledger_config.chain.ledger_type)
|
|
1906
1870
|
ledger_api = wallet.ledger_api(chain=ledger_config.chain, rpc=ledger_config.rpc)
|
|
1871
|
+
|
|
1872
|
+
if (
|
|
1873
|
+
chain_config.chain_data.token == NON_EXISTENT_TOKEN
|
|
1874
|
+
or chain_config.chain_data.multisig == ZERO_ADDRESS
|
|
1875
|
+
):
|
|
1876
|
+
self.logger.info("Service is not minted or Safe not deployed.")
|
|
1877
|
+
return 0
|
|
1878
|
+
|
|
1907
1879
|
self.logger.info(
|
|
1908
1880
|
f"OLAS Balance on service Safe {chain_config.chain_data.multisig}: "
|
|
1909
1881
|
f"{get_asset_balance(ledger_api, OLAS[Chain(chain)], chain_config.chain_data.multisig)}"
|
|
@@ -1916,10 +1888,11 @@ class ServiceManager:
|
|
|
1916
1888
|
staking_program_id=current_staking_program,
|
|
1917
1889
|
)
|
|
1918
1890
|
if staking_contract is None:
|
|
1919
|
-
|
|
1891
|
+
self.logger.warning(
|
|
1920
1892
|
"No staking contract found for the "
|
|
1921
1893
|
f"{current_staking_program=}. Not claiming the rewards."
|
|
1922
1894
|
)
|
|
1895
|
+
return 0
|
|
1923
1896
|
|
|
1924
1897
|
sftxb = self.get_eth_safe_tx_builder(ledger_config=ledger_config)
|
|
1925
1898
|
if not sftxb.staking_rewards_claimable(
|
|
@@ -1964,22 +1937,13 @@ class ServiceManager:
|
|
|
1964
1937
|
def fund_service( # pylint: disable=too-many-arguments,too-many-locals
|
|
1965
1938
|
self,
|
|
1966
1939
|
service_config_id: str,
|
|
1967
|
-
|
|
1968
|
-
from_safe: bool = True,
|
|
1969
|
-
task_id: t.Optional[str] = None,
|
|
1940
|
+
amounts: ChainAmounts,
|
|
1970
1941
|
) -> None:
|
|
1971
1942
|
"""Fund service if required."""
|
|
1972
1943
|
service = self.load(service_config_id=service_config_id)
|
|
1944
|
+
self.funding_manager.fund_service(service=service, amounts=amounts)
|
|
1973
1945
|
|
|
1974
|
-
|
|
1975
|
-
self.logger.info(f"[FUNDING_JOB] [{task_id=}] Funding {chain=}")
|
|
1976
|
-
self.fund_service_single_chain(
|
|
1977
|
-
service_config_id=service_config_id,
|
|
1978
|
-
funding_values=funding_values,
|
|
1979
|
-
from_safe=from_safe,
|
|
1980
|
-
chain=chain,
|
|
1981
|
-
)
|
|
1982
|
-
|
|
1946
|
+
# TODO deprecate
|
|
1983
1947
|
def fund_service_single_chain( # pylint: disable=too-many-arguments,too-many-locals,too-many-statements
|
|
1984
1948
|
self,
|
|
1985
1949
|
service_config_id: str,
|
|
@@ -2012,7 +1976,10 @@ class ServiceManager:
|
|
|
2012
1976
|
else:
|
|
2013
1977
|
on_chain_operations_buffer = (
|
|
2014
1978
|
chain_data.user_params.cost_of_bond
|
|
2015
|
-
* (
|
|
1979
|
+
* (
|
|
1980
|
+
MIN_SECURITY_DEPOSIT
|
|
1981
|
+
+ MIN_AGENT_BOND * len(service.agent_addresses)
|
|
1982
|
+
)
|
|
2016
1983
|
)
|
|
2017
1984
|
|
|
2018
1985
|
asset_funding_values = (
|
|
@@ -2057,10 +2024,13 @@ class ServiceManager:
|
|
|
2057
2024
|
to_transfer = max(
|
|
2058
2025
|
min(available_balance, target_balance - agent_balance), 0
|
|
2059
2026
|
)
|
|
2027
|
+
if to_transfer <= 0:
|
|
2028
|
+
continue
|
|
2029
|
+
|
|
2060
2030
|
self.logger.info(
|
|
2061
2031
|
f"[FUNDING_JOB] Transferring {to_transfer} units (asset {asset_address}) to agent {agent_address}"
|
|
2062
2032
|
)
|
|
2063
|
-
wallet.
|
|
2033
|
+
wallet.transfer(
|
|
2064
2034
|
asset=asset_address,
|
|
2065
2035
|
to=agent_address,
|
|
2066
2036
|
amount=int(to_transfer),
|
|
@@ -2129,7 +2099,7 @@ class ServiceManager:
|
|
|
2129
2099
|
# when not enough funds are present, and the FE doesn't let the user to start the agent.
|
|
2130
2100
|
# Ideally this error should be allowed, and then the FE should ask the user for more funds.
|
|
2131
2101
|
with suppress(RuntimeError):
|
|
2132
|
-
wallet.
|
|
2102
|
+
wallet.transfer(
|
|
2133
2103
|
asset=asset_address,
|
|
2134
2104
|
to=t.cast(str, chain_data.multisig),
|
|
2135
2105
|
amount=int(to_transfer),
|
|
@@ -2137,6 +2107,7 @@ class ServiceManager:
|
|
|
2137
2107
|
rpc=rpc or ledger_config.rpc,
|
|
2138
2108
|
)
|
|
2139
2109
|
|
|
2110
|
+
# TODO Deprecate
|
|
2140
2111
|
# TODO This method is possibly not used anymore
|
|
2141
2112
|
def fund_service_erc20( # pylint: disable=too-many-arguments,too-many-locals
|
|
2142
2113
|
self,
|
|
@@ -2174,9 +2145,12 @@ class ServiceManager:
|
|
|
2174
2145
|
agent_topup
|
|
2175
2146
|
or chain_data.user_params.fund_requirements[ZERO_ADDRESS].agent
|
|
2176
2147
|
)
|
|
2148
|
+
if to_transfer <= 0:
|
|
2149
|
+
continue
|
|
2150
|
+
|
|
2177
2151
|
self.logger.info(f"Transferring {to_transfer} units to {agent_address}")
|
|
2178
|
-
wallet.
|
|
2179
|
-
|
|
2152
|
+
wallet.transfer(
|
|
2153
|
+
asset=token,
|
|
2180
2154
|
to=agent_address,
|
|
2181
2155
|
amount=int(to_transfer),
|
|
2182
2156
|
chain=ledger_config.chain,
|
|
@@ -2201,150 +2175,36 @@ class ServiceManager:
|
|
|
2201
2175
|
safe_topup
|
|
2202
2176
|
or chain_data.user_params.fund_requirements[ZERO_ADDRESS].safe
|
|
2203
2177
|
)
|
|
2178
|
+
if to_transfer <= 0:
|
|
2179
|
+
return
|
|
2180
|
+
|
|
2204
2181
|
self.logger.info(
|
|
2205
2182
|
f"Transferring {to_transfer} units to {chain_data.multisig}"
|
|
2206
2183
|
)
|
|
2207
|
-
wallet.
|
|
2208
|
-
|
|
2184
|
+
wallet.transfer(
|
|
2185
|
+
asset=token,
|
|
2209
2186
|
to=t.cast(str, chain_data.multisig),
|
|
2210
2187
|
amount=int(to_transfer),
|
|
2211
2188
|
chain=ledger_config.chain,
|
|
2212
2189
|
rpc=rpc or ledger_config.rpc,
|
|
2213
2190
|
)
|
|
2214
2191
|
|
|
2215
|
-
def
|
|
2216
|
-
self,
|
|
2217
|
-
service_config_id: str,
|
|
2218
|
-
withdrawal_address: str,
|
|
2219
|
-
chain: Chain,
|
|
2220
|
-
) -> None:
|
|
2221
|
-
"""Drain the funds out of the service safe."""
|
|
2222
|
-
self.logger.info(
|
|
2223
|
-
f"Draining the safe of service: {service_config_id} on chain {chain.value}"
|
|
2224
|
-
)
|
|
2225
|
-
service = self.load(service_config_id=service_config_id)
|
|
2226
|
-
chain_config = service.chain_configs[chain.value]
|
|
2227
|
-
ledger_config = chain_config.ledger_config
|
|
2228
|
-
chain_data = chain_config.chain_data
|
|
2229
|
-
wallet = self.wallet_manager.load(ledger_config.chain.ledger_type)
|
|
2230
|
-
ledger_api = wallet.ledger_api(chain=ledger_config.chain, rpc=ledger_config.rpc)
|
|
2231
|
-
ethereum_crypto = KeysManager().get_crypto_instance(service.agent_addresses[0])
|
|
2232
|
-
withdrawal_address = Web3.to_checksum_address(withdrawal_address)
|
|
2233
|
-
|
|
2234
|
-
# drain ERC20 tokens from service safe
|
|
2235
|
-
for token_name, token_address in (
|
|
2236
|
-
("OLAS", OLAS[chain]),
|
|
2237
|
-
(
|
|
2238
|
-
f"W{get_currency_denom(chain)}",
|
|
2239
|
-
WRAPPED_NATIVE_ASSET[chain],
|
|
2240
|
-
),
|
|
2241
|
-
("USDC", USDC[chain]),
|
|
2242
|
-
):
|
|
2243
|
-
token_instance = registry_contracts.erc20.get_instance(
|
|
2244
|
-
ledger_api=ledger_api,
|
|
2245
|
-
contract_address=token_address,
|
|
2246
|
-
)
|
|
2247
|
-
balance = token_instance.functions.balanceOf(chain_data.multisig).call()
|
|
2248
|
-
if balance == 0:
|
|
2249
|
-
self.logger.info(
|
|
2250
|
-
f"No {token_name} to drain from service safe: {chain_data.multisig}"
|
|
2251
|
-
)
|
|
2252
|
-
continue
|
|
2253
|
-
|
|
2254
|
-
self.logger.info(
|
|
2255
|
-
f"Draining {balance} {token_name} out of service safe: {chain_data.multisig}"
|
|
2256
|
-
)
|
|
2257
|
-
transfer_erc20_from_safe(
|
|
2258
|
-
ledger_api=ledger_api,
|
|
2259
|
-
crypto=ethereum_crypto,
|
|
2260
|
-
safe=chain_data.multisig,
|
|
2261
|
-
token=token_address,
|
|
2262
|
-
to=withdrawal_address,
|
|
2263
|
-
amount=balance,
|
|
2264
|
-
)
|
|
2265
|
-
|
|
2266
|
-
# drain native asset from service safe
|
|
2267
|
-
balance = ledger_api.get_balance(chain_data.multisig)
|
|
2268
|
-
if balance == 0:
|
|
2269
|
-
self.logger.info(
|
|
2270
|
-
f"No {get_currency_denom(chain)} to drain from service safe: {chain_data.multisig}"
|
|
2271
|
-
)
|
|
2272
|
-
else:
|
|
2273
|
-
self.logger.info(
|
|
2274
|
-
f"Draining {balance} {get_currency_denom(chain)} out of service safe: {chain_data.multisig}"
|
|
2275
|
-
)
|
|
2276
|
-
transfer_from_safe(
|
|
2277
|
-
ledger_api=ledger_api,
|
|
2278
|
-
crypto=ethereum_crypto,
|
|
2279
|
-
safe=chain_data.multisig,
|
|
2280
|
-
to=withdrawal_address,
|
|
2281
|
-
amount=balance,
|
|
2282
|
-
)
|
|
2283
|
-
|
|
2284
|
-
self.logger.info(f"{service.name} safe drained ({service_config_id=})")
|
|
2285
|
-
|
|
2286
|
-
async def funding_job(
|
|
2287
|
-
self,
|
|
2288
|
-
service_config_id: str,
|
|
2289
|
-
loop: t.Optional[asyncio.AbstractEventLoop] = None,
|
|
2290
|
-
from_safe: bool = True,
|
|
2192
|
+
def drain(
|
|
2193
|
+
self, service_config_id: str, chain_str: str, withdrawal_address: str
|
|
2291
2194
|
) -> None:
|
|
2292
|
-
"""
|
|
2293
|
-
loop = loop or asyncio.get_event_loop()
|
|
2195
|
+
"""Drain service safe and agent EOAs."""
|
|
2294
2196
|
service = self.load(service_config_id=service_config_id)
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
{
|
|
2307
|
-
asset_address: {
|
|
2308
|
-
"agent": {
|
|
2309
|
-
"topup": fund_requirements.agent,
|
|
2310
|
-
"threshold": int(
|
|
2311
|
-
fund_requirements.agent
|
|
2312
|
-
* DEFAULT_TOPUP_THRESHOLD
|
|
2313
|
-
),
|
|
2314
|
-
},
|
|
2315
|
-
"safe": {
|
|
2316
|
-
"topup": fund_requirements.safe,
|
|
2317
|
-
"threshold": int(
|
|
2318
|
-
fund_requirements.safe * DEFAULT_TOPUP_THRESHOLD
|
|
2319
|
-
),
|
|
2320
|
-
},
|
|
2321
|
-
}
|
|
2322
|
-
for asset_address, fund_requirements in chain_config.chain_data.user_params.fund_requirements.items()
|
|
2323
|
-
},
|
|
2324
|
-
from_safe,
|
|
2325
|
-
task_id,
|
|
2326
|
-
)
|
|
2327
|
-
except Exception: # pylint: disable=broad-except
|
|
2328
|
-
logging.info(
|
|
2329
|
-
f"Error occured while funding the service\n{traceback.format_exc()}"
|
|
2330
|
-
)
|
|
2331
|
-
|
|
2332
|
-
# try claiming rewards every hour
|
|
2333
|
-
if last_claim + 3600 < time():
|
|
2334
|
-
try:
|
|
2335
|
-
await loop.run_in_executor(
|
|
2336
|
-
executor,
|
|
2337
|
-
self.claim_on_chain_from_safe,
|
|
2338
|
-
service_config_id,
|
|
2339
|
-
service.home_chain,
|
|
2340
|
-
)
|
|
2341
|
-
except Exception: # pylint: disable=broad-except
|
|
2342
|
-
logging.info(
|
|
2343
|
-
f"Error occured while claiming rewards\n{traceback.format_exc()}"
|
|
2344
|
-
)
|
|
2345
|
-
last_claim = time()
|
|
2346
|
-
|
|
2347
|
-
await asyncio.sleep(60)
|
|
2197
|
+
chain = Chain(chain_str)
|
|
2198
|
+
self.funding_manager.drain_service_safe(
|
|
2199
|
+
service=service,
|
|
2200
|
+
withdrawal_address=withdrawal_address,
|
|
2201
|
+
chain=chain,
|
|
2202
|
+
)
|
|
2203
|
+
self.funding_manager.drain_agents_eoas(
|
|
2204
|
+
service=service,
|
|
2205
|
+
withdrawal_address=withdrawal_address,
|
|
2206
|
+
chain=chain,
|
|
2207
|
+
)
|
|
2348
2208
|
|
|
2349
2209
|
def deploy_service_locally(
|
|
2350
2210
|
self,
|
|
@@ -2418,6 +2278,14 @@ class ServiceManager:
|
|
|
2418
2278
|
)
|
|
2419
2279
|
return service
|
|
2420
2280
|
|
|
2281
|
+
def funding_requirements( # pylint: disable=too-many-locals,too-many-statements,too-many-nested-blocks
|
|
2282
|
+
self, service_config_id: str
|
|
2283
|
+
) -> t.Dict:
|
|
2284
|
+
"""Get the funding requirements for a service."""
|
|
2285
|
+
service = self.load(service_config_id=service_config_id)
|
|
2286
|
+
return self.funding_manager.funding_requirements(service)
|
|
2287
|
+
|
|
2288
|
+
# TODO deprecate
|
|
2421
2289
|
def refill_requirements( # pylint: disable=too-many-locals,too-many-statements,too-many-nested-blocks
|
|
2422
2290
|
self, service_config_id: str
|
|
2423
2291
|
) -> t.Dict:
|
|
@@ -2621,6 +2489,7 @@ class ServiceManager:
|
|
|
2621
2489
|
"allow_start_agent": allow_start_agent,
|
|
2622
2490
|
}
|
|
2623
2491
|
|
|
2492
|
+
# TODO deprecate
|
|
2624
2493
|
def _compute_bonded_assets( # pylint: disable=too-many-locals
|
|
2625
2494
|
self, service_config_id: str, chain: str
|
|
2626
2495
|
) -> t.Dict:
|
|
@@ -2736,6 +2605,7 @@ class ServiceManager:
|
|
|
2736
2605
|
|
|
2737
2606
|
return dict(bonded_assets)
|
|
2738
2607
|
|
|
2608
|
+
# TODO deprecate
|
|
2739
2609
|
def _compute_protocol_asset_requirements( # pylint: disable=too-many-locals
|
|
2740
2610
|
self, service_config_id: str, chain: str
|
|
2741
2611
|
) -> t.Dict:
|
|
@@ -2768,6 +2638,7 @@ class ServiceManager:
|
|
|
2768
2638
|
),
|
|
2769
2639
|
)
|
|
2770
2640
|
|
|
2641
|
+
# TODO address this comment in FundingManager
|
|
2771
2642
|
# This computation assumes the service will be/has been minted with these
|
|
2772
2643
|
# parameters. Otherwise, these values should be retrieved on-chain as follows:
|
|
2773
2644
|
# - agent_bonds: by combining the output of ServiceRegistry .getAgentParams .getService
|
|
@@ -2783,6 +2654,7 @@ class ServiceManager:
|
|
|
2783
2654
|
|
|
2784
2655
|
return dict(service_asset_requirements)
|
|
2785
2656
|
|
|
2657
|
+
# TODO deprecate
|
|
2786
2658
|
@staticmethod
|
|
2787
2659
|
def _compute_refill_requirement(
|
|
2788
2660
|
asset_funding_values: t.Dict,
|
|
@@ -2863,12 +2735,13 @@ class ServiceManager:
|
|
|
2863
2735
|
"recommended_refill": recommended_refill,
|
|
2864
2736
|
}
|
|
2865
2737
|
|
|
2738
|
+
# TODO deprecate
|
|
2866
2739
|
@staticmethod
|
|
2867
2740
|
def get_master_eoa_native_funding_values(
|
|
2868
2741
|
master_safe_exists: bool, chain: Chain, balance: int
|
|
2869
2742
|
) -> t.Dict:
|
|
2870
2743
|
"""Get Master EOA native funding values."""
|
|
2871
2744
|
|
|
2872
|
-
topup =
|
|
2745
|
+
topup = DEFAULT_EOA_TOPUPS[chain][ZERO_ADDRESS]
|
|
2873
2746
|
threshold = topup / 2 if master_safe_exists else topup
|
|
2874
2747
|
return {"topup": topup, "threshold": threshold, "balance": balance}
|