olas-operate-middleware 0.1.0rc59__py3-none-any.whl → 0.13.2__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 (98) hide show
  1. olas_operate_middleware-0.13.2.dist-info/METADATA +75 -0
  2. olas_operate_middleware-0.13.2.dist-info/RECORD +101 -0
  3. {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info}/WHEEL +1 -1
  4. operate/__init__.py +17 -0
  5. operate/account/user.py +35 -9
  6. operate/bridge/bridge_manager.py +470 -0
  7. operate/bridge/providers/lifi_provider.py +377 -0
  8. operate/bridge/providers/native_bridge_provider.py +677 -0
  9. operate/bridge/providers/provider.py +469 -0
  10. operate/bridge/providers/relay_provider.py +457 -0
  11. operate/cli.py +1565 -417
  12. operate/constants.py +60 -12
  13. operate/data/README.md +19 -0
  14. operate/data/contracts/{service_staking_token → dual_staking_token}/__init__.py +2 -2
  15. operate/data/contracts/dual_staking_token/build/DualStakingToken.json +443 -0
  16. operate/data/contracts/dual_staking_token/contract.py +132 -0
  17. operate/data/contracts/dual_staking_token/contract.yaml +23 -0
  18. operate/{ledger/base.py → data/contracts/foreign_omnibridge/__init__.py} +2 -19
  19. operate/data/contracts/foreign_omnibridge/build/ForeignOmnibridge.json +1372 -0
  20. operate/data/contracts/foreign_omnibridge/contract.py +130 -0
  21. operate/data/contracts/foreign_omnibridge/contract.yaml +23 -0
  22. operate/{ledger/solana.py → data/contracts/home_omnibridge/__init__.py} +2 -20
  23. operate/data/contracts/home_omnibridge/build/HomeOmnibridge.json +1421 -0
  24. operate/data/contracts/home_omnibridge/contract.py +80 -0
  25. operate/data/contracts/home_omnibridge/contract.yaml +23 -0
  26. operate/data/contracts/l1_standard_bridge/__init__.py +20 -0
  27. operate/data/contracts/l1_standard_bridge/build/L1StandardBridge.json +831 -0
  28. operate/data/contracts/l1_standard_bridge/contract.py +158 -0
  29. operate/data/contracts/l1_standard_bridge/contract.yaml +23 -0
  30. operate/data/contracts/l2_standard_bridge/__init__.py +20 -0
  31. operate/data/contracts/l2_standard_bridge/build/L2StandardBridge.json +626 -0
  32. operate/data/contracts/l2_standard_bridge/contract.py +130 -0
  33. operate/data/contracts/l2_standard_bridge/contract.yaml +23 -0
  34. operate/data/contracts/mech_activity/__init__.py +20 -0
  35. operate/data/contracts/mech_activity/build/MechActivity.json +111 -0
  36. operate/data/contracts/mech_activity/contract.py +44 -0
  37. operate/data/contracts/mech_activity/contract.yaml +23 -0
  38. operate/data/contracts/optimism_mintable_erc20/__init__.py +20 -0
  39. operate/data/contracts/optimism_mintable_erc20/build/OptimismMintableERC20.json +491 -0
  40. operate/data/contracts/optimism_mintable_erc20/contract.py +45 -0
  41. operate/data/contracts/optimism_mintable_erc20/contract.yaml +23 -0
  42. operate/data/contracts/recovery_module/__init__.py +20 -0
  43. operate/data/contracts/recovery_module/build/RecoveryModule.json +811 -0
  44. operate/data/contracts/recovery_module/contract.py +61 -0
  45. operate/data/contracts/recovery_module/contract.yaml +23 -0
  46. operate/data/contracts/requester_activity_checker/__init__.py +20 -0
  47. operate/data/contracts/requester_activity_checker/build/RequesterActivityChecker.json +111 -0
  48. operate/data/contracts/requester_activity_checker/contract.py +33 -0
  49. operate/data/contracts/requester_activity_checker/contract.yaml +23 -0
  50. operate/data/contracts/staking_token/__init__.py +20 -0
  51. operate/data/contracts/staking_token/build/StakingToken.json +1336 -0
  52. operate/data/contracts/{service_staking_token → staking_token}/contract.py +27 -13
  53. operate/data/contracts/staking_token/contract.yaml +23 -0
  54. operate/data/contracts/uniswap_v2_erc20/contract.yaml +3 -1
  55. operate/data/contracts/uniswap_v2_erc20/tests/__init__.py +20 -0
  56. operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py +363 -0
  57. operate/keys.py +118 -33
  58. operate/ledger/__init__.py +159 -56
  59. operate/ledger/profiles.py +321 -18
  60. operate/migration.py +555 -0
  61. operate/{http → operate_http}/__init__.py +3 -2
  62. operate/{http → operate_http}/exceptions.py +6 -4
  63. operate/operate_types.py +544 -0
  64. operate/pearl.py +13 -1
  65. operate/quickstart/analyse_logs.py +118 -0
  66. operate/quickstart/claim_staking_rewards.py +104 -0
  67. operate/quickstart/reset_configs.py +106 -0
  68. operate/quickstart/reset_password.py +70 -0
  69. operate/quickstart/reset_staking.py +145 -0
  70. operate/quickstart/run_service.py +726 -0
  71. operate/quickstart/stop_service.py +72 -0
  72. operate/quickstart/terminate_on_chain_service.py +83 -0
  73. operate/quickstart/utils.py +298 -0
  74. operate/resource.py +62 -3
  75. operate/services/agent_runner.py +202 -0
  76. operate/services/deployment_runner.py +868 -0
  77. operate/services/funding_manager.py +929 -0
  78. operate/services/health_checker.py +280 -0
  79. operate/services/manage.py +2356 -620
  80. operate/services/protocol.py +1246 -340
  81. operate/services/service.py +756 -391
  82. operate/services/utils/mech.py +103 -0
  83. operate/services/utils/tendermint.py +86 -12
  84. operate/settings.py +70 -0
  85. operate/utils/__init__.py +135 -0
  86. operate/utils/gnosis.py +407 -80
  87. operate/utils/single_instance.py +226 -0
  88. operate/utils/ssl.py +133 -0
  89. operate/wallet/master.py +708 -123
  90. operate/wallet/wallet_recovery_manager.py +507 -0
  91. olas_operate_middleware-0.1.0rc59.dist-info/METADATA +0 -304
  92. olas_operate_middleware-0.1.0rc59.dist-info/RECORD +0 -41
  93. operate/data/contracts/service_staking_token/build/ServiceStakingToken.json +0 -1273
  94. operate/data/contracts/service_staking_token/contract.yaml +0 -23
  95. operate/ledger/ethereum.py +0 -48
  96. operate/types.py +0 -260
  97. {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info}/entry_points.txt +0 -0
  98. {olas_operate_middleware-0.1.0rc59.dist-info → olas_operate_middleware-0.13.2.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,104 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2024 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+ """Claim staking rewards."""
20
+
21
+ import json
22
+ import logging
23
+ import os
24
+ import warnings
25
+ from typing import TYPE_CHECKING, cast
26
+
27
+ from operate.constants import SAFE_WEBAPP_URL
28
+ from operate.quickstart.run_service import (
29
+ ask_password_if_needed,
30
+ configure_local_config,
31
+ get_service,
32
+ load_local_config,
33
+ )
34
+ from operate.quickstart.utils import ask_yes_or_no, print_section
35
+
36
+
37
+ if TYPE_CHECKING:
38
+ from operate.cli import OperateApp
39
+
40
+ warnings.filterwarnings("ignore", category=UserWarning)
41
+
42
+
43
+ def claim_staking_rewards(operate: "OperateApp", config_path: str) -> None:
44
+ """Claim staking rewards."""
45
+ with open(config_path, "r") as config_file:
46
+ template = json.load(config_file)
47
+
48
+ print_section(f"Claim staking rewards for {template['name']}")
49
+
50
+ # check if agent was started before
51
+ config = load_local_config(
52
+ operate=operate, service_name=cast(str, template["name"])
53
+ )
54
+ if not config.path.exists():
55
+ print("No previous agent setup found. Exiting.")
56
+ return
57
+
58
+ print(
59
+ "This script will claim the OLAS staking rewards "
60
+ "accrued in the current staking contract and transfer them to your service safe."
61
+ )
62
+
63
+ if not ask_yes_or_no("Do you want to continue?"):
64
+ print("Cancelled.")
65
+ return
66
+
67
+ print("")
68
+
69
+ ask_password_if_needed(operate)
70
+ config = configure_local_config(template, operate)
71
+ manager = operate.service_manager()
72
+ service = get_service(manager, template)
73
+
74
+ # reload manger and config after setting operate.password
75
+ manager = operate.service_manager()
76
+ chain_config = service.chain_configs[config.principal_chain]
77
+ wallet = operate.wallet_manager.load(
78
+ ledger_type=chain_config.ledger_config.chain.ledger_type
79
+ )
80
+ config = load_local_config(operate=operate, service_name=cast(str, service.name))
81
+ assert ( # nosec
82
+ config.principal_chain is not None
83
+ ), "Principal chain not set in quickstart config"
84
+ assert config.rpc is not None, "RPC not set in quickstart config" # nosec
85
+ os.environ["CUSTOM_CHAIN_RPC"] = config.rpc[config.principal_chain]
86
+
87
+ try:
88
+ manager.claim_on_chain_from_safe(
89
+ service_config_id=service.service_config_id,
90
+ chain=config.principal_chain,
91
+ )
92
+ except RuntimeError as e:
93
+ print(
94
+ "The transaction was reverted. "
95
+ "This may be caused because your service does not have rewards to claim.\n"
96
+ )
97
+ logging.error(e)
98
+ return
99
+
100
+ master_safe = wallet.safes[chain_config.ledger_config.chain]
101
+ print(
102
+ f"Claimed staking rewards are transferred to your Master Safe {master_safe}.\n"
103
+ )
104
+ print(f"You may connect to the Master Safe at {SAFE_WEBAPP_URL}{master_safe}")
@@ -0,0 +1,106 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2023-2024 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+ """Reset configurations."""
20
+
21
+ import json
22
+ from typing import Callable, Optional, TYPE_CHECKING, cast
23
+
24
+ from operate.quickstart.run_service import load_local_config
25
+ from operate.quickstart.utils import (
26
+ ask_or_get_from_env,
27
+ ask_yes_or_no,
28
+ check_rpc,
29
+ print_section,
30
+ print_title,
31
+ )
32
+
33
+
34
+ if TYPE_CHECKING:
35
+ from operate.cli import OperateApp
36
+
37
+
38
+ def _ask_to_change(
39
+ name: str,
40
+ env_var: str,
41
+ old_value: str,
42
+ hidden: bool = False,
43
+ validator: Callable[[Optional[str]], bool] = lambda x: False if x is None else True,
44
+ ) -> str:
45
+ """Ask user if they want to change a configuration value."""
46
+ old_value_str = old_value
47
+ if hidden:
48
+ if len(old_value_str) < 4:
49
+ old_value_str = "*" * len(old_value_str)
50
+ else:
51
+ old_value_str = "*" * len(old_value_str[:-4]) + old_value_str[-4:]
52
+
53
+ print(f"\nCurrent '{name}' is set to: {old_value_str}")
54
+ if ask_yes_or_no(f"Do you want to change the '{name}'?"):
55
+ new_value = None
56
+ while not validator(new_value):
57
+ new_value = ask_or_get_from_env(
58
+ prompt=f"Enter new value for '{name}' {'[hidden]' if hidden else ''}: ",
59
+ env_var_name=env_var,
60
+ is_pass=hidden,
61
+ )
62
+
63
+ return str(new_value)
64
+
65
+ return old_value
66
+
67
+
68
+ def reset_configs(operate: "OperateApp", config_path: str) -> None:
69
+ """Reset configurations."""
70
+ with open(config_path, "r") as config_file:
71
+ template = json.load(config_file)
72
+
73
+ print_title(f"Reset your {template['name']} configurations")
74
+
75
+ # check if agent was started before
76
+ config = load_local_config(
77
+ operate=operate, service_name=cast(str, template["name"])
78
+ )
79
+ if not config.path.exists():
80
+ print("No previous agent setup found. Exiting.")
81
+ return
82
+
83
+ if config.rpc is None:
84
+ config.rpc = {}
85
+
86
+ for chain_name in config.rpc:
87
+ config.rpc[chain_name] = _ask_to_change(
88
+ name=f"{chain_name.capitalize()} RPC URL",
89
+ env_var=f"{chain_name.upper()}_LEDGER_RPC",
90
+ old_value=config.rpc[chain_name],
91
+ hidden=True,
92
+ validator=lambda x: check_rpc(chain_name, x), # noqa: B023
93
+ )
94
+
95
+ if config.user_provided_args is None:
96
+ config.user_provided_args = {}
97
+
98
+ for env_var in config.user_provided_args:
99
+ config.user_provided_args[env_var] = _ask_to_change(
100
+ name=env_var,
101
+ env_var=env_var,
102
+ old_value=config.user_provided_args[env_var],
103
+ )
104
+
105
+ config.store()
106
+ print_section("Configurations updated")
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2023-2024 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+ """Reset password."""
20
+
21
+ from typing import TYPE_CHECKING
22
+
23
+ from operate.account.user import UserAccount
24
+ from operate.constants import USER_JSON
25
+ from operate.quickstart.run_service import ask_confirm_password
26
+ from operate.quickstart.utils import ask_or_get_from_env, print_section, print_title
27
+
28
+
29
+ if TYPE_CHECKING:
30
+ from operate.cli import OperateApp
31
+
32
+
33
+ def reset_password(operate: "OperateApp") -> None:
34
+ """Reset password."""
35
+ print_title("Reset your password")
36
+
37
+ # check if agent was started before
38
+ if not (operate._path / USER_JSON).exists():
39
+ print("No previous agent setup found. Exiting.")
40
+ return
41
+
42
+ old_password = None
43
+ while old_password is None:
44
+ old_password = ask_or_get_from_env(
45
+ "\nEnter local user account password [hidden input]: ",
46
+ True,
47
+ "OLD_OPERATE_PASSWORD",
48
+ )
49
+ if operate.user_account.is_valid(password=old_password):
50
+ break
51
+ old_password = None
52
+ print("Invalid password!")
53
+
54
+ print_section("Update local user account")
55
+ new_password = ask_confirm_password()
56
+ print("Resetting password of user account...")
57
+ UserAccount.new(
58
+ password=old_password,
59
+ path=operate._path / USER_JSON,
60
+ ).update(
61
+ old_password=old_password,
62
+ new_password=new_password,
63
+ )
64
+
65
+ print('Resetting password of "ethereum" wallet...')
66
+ operate.password = old_password
67
+ operate.wallet_manager.update_password(new_password=new_password)
68
+ operate.keys_manager.update_password(new_password=new_password)
69
+
70
+ print_section("Password reset done!")
@@ -0,0 +1,145 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ------------------------------------------------------------------------------
3
+ #
4
+ # Copyright 2023-2024 Valory AG
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ # ------------------------------------------------------------------------------
19
+ """Reset staking."""
20
+
21
+ import json
22
+ import os
23
+ from typing import TYPE_CHECKING, cast
24
+
25
+ from operate.constants import NO_STAKING_PROGRAM_ID
26
+ from operate.ledger.profiles import get_staking_contract
27
+ from operate.quickstart.run_service import (
28
+ CUSTOM_PROGRAM_ID,
29
+ ask_password_if_needed,
30
+ configure_local_config,
31
+ ensure_enough_funds,
32
+ get_service,
33
+ load_local_config,
34
+ )
35
+ from operate.quickstart.utils import ask_yes_or_no, print_section, print_title
36
+ from operate.services.protocol import StakingState
37
+
38
+
39
+ if TYPE_CHECKING:
40
+ from operate.cli import OperateApp
41
+
42
+
43
+ def reset_staking(operate: "OperateApp", config_path: str) -> None:
44
+ """Reset staking."""
45
+ with open(config_path, "r") as config_file:
46
+ template = json.load(config_file)
47
+
48
+ print_title("Reset your staking program preference")
49
+
50
+ # check if agent was started before
51
+ config = load_local_config(
52
+ operate=operate, service_name=cast(str, template["name"])
53
+ )
54
+ if not config.path.exists():
55
+ print("No previous agent setup found. Exiting.")
56
+ return
57
+
58
+ ask_password_if_needed(operate)
59
+ config = configure_local_config(template, operate)
60
+ assert ( # nosec
61
+ config.principal_chain is not None
62
+ ), "Principal chain not set in quickstart config"
63
+
64
+ if not config.staking_program_id:
65
+ print("No staking program preference found. Exiting.")
66
+ return
67
+
68
+ print(
69
+ f"Your current staking program preference is set to '{config.staking_program_id}'.\n"
70
+ )
71
+ print(
72
+ "You can reset your preference. "
73
+ "However, your agent might not be able to switch between staking contracts "
74
+ "until it has been staked for a minimum staking period in the current program.\n"
75
+ )
76
+
77
+ if not ask_yes_or_no(
78
+ "Please, ensure that your service is stopped (./stop_service.sh) before proceeding. "
79
+ "Do you want to continue?"
80
+ ):
81
+ print("Cancelled.")
82
+ return
83
+
84
+ manager = operate.service_manager()
85
+ service = get_service(manager, template)
86
+
87
+ # Check if service can be unstaked from current program
88
+ os.environ["CUSTOM_CHAIN_RPC"] = service.chain_configs[
89
+ config.principal_chain
90
+ ].ledger_config.rpc
91
+ sftxb = manager.get_eth_safe_tx_builder(
92
+ ledger_config=service.chain_configs[config.principal_chain].ledger_config
93
+ )
94
+ service_id = service.chain_configs[config.principal_chain].chain_data.token
95
+ staking_contract = get_staking_contract(
96
+ chain=config.principal_chain,
97
+ staking_program_id=config.staking_program_id,
98
+ )
99
+
100
+ if (
101
+ config.staking_program_id is not None
102
+ and config.staking_program_id not in (NO_STAKING_PROGRAM_ID, CUSTOM_PROGRAM_ID)
103
+ and sftxb.staking_status(
104
+ service_id=service_id, staking_contract=staking_contract
105
+ )
106
+ in (StakingState.STAKED, StakingState.EVICTED)
107
+ ):
108
+ if not sftxb.can_unstake(
109
+ service_id=service_id,
110
+ staking_contract=staking_contract,
111
+ ):
112
+ print_section("Cannot Reset Staking Preference")
113
+ print(
114
+ "Your service cannot be unstaked at this time. This could be due to:\n"
115
+ "- Minimum staking period not elapsed\n"
116
+ "- Available rewards pending\n\n"
117
+ "Please try again once the staking conditions allow unstaking."
118
+ )
119
+ return
120
+
121
+ if not ask_yes_or_no(
122
+ "Service can be unstaked. Would you like to proceed with unstaking and reset?"
123
+ ):
124
+ print("Cancelled.")
125
+ return
126
+
127
+ # Unstake the service
128
+ ensure_enough_funds(operate, service)
129
+ manager.unstake_service_on_chain_from_safe(
130
+ service_config_id=service.service_config_id,
131
+ chain=config.principal_chain,
132
+ staking_program_id=config.staking_program_id,
133
+ )
134
+ print_section("Service has been unstaked successfully")
135
+
136
+ # Update local config and service template
137
+ config.staking_program_id = None
138
+ config.store()
139
+ config = configure_local_config(template, operate)
140
+ service = get_service(manager, template)
141
+ manager.update(
142
+ service_config_id=service.service_config_id,
143
+ service_template=template,
144
+ )
145
+ print("\nStaking preference has been reset successfully.")