olas-operate-middleware 0.14.2__tar.gz → 0.14.3__tar.gz

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.

Potentially problematic release.


This version of olas-operate-middleware might be problematic. Click here for more details.

Files changed (97) hide show
  1. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/PKG-INFO +6 -6
  2. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/cli.py +63 -1
  3. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/constants.py +1 -0
  4. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/ledger/profiles.py +6 -0
  5. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/operate_types.py +29 -1
  6. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/run_service.py +2 -0
  7. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/resource.py +10 -0
  8. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/service.py +100 -4
  9. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/pyproject.toml +6 -6
  10. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/LICENSE +0 -0
  11. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/README.md +0 -0
  12. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/__init__.py +0 -0
  13. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/account/__init__.py +0 -0
  14. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/account/user.py +0 -0
  15. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/bridge/bridge_manager.py +0 -0
  16. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/bridge/providers/lifi_provider.py +0 -0
  17. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/bridge/providers/native_bridge_provider.py +0 -0
  18. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/bridge/providers/provider.py +0 -0
  19. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/bridge/providers/relay_provider.py +0 -0
  20. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/README.md +0 -0
  21. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/__init__.py +0 -0
  22. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/__init__.py +0 -0
  23. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/dual_staking_token/__init__.py +0 -0
  24. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/dual_staking_token/build/DualStakingToken.json +0 -0
  25. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/dual_staking_token/contract.py +0 -0
  26. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/dual_staking_token/contract.yaml +0 -0
  27. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/foreign_omnibridge/__init__.py +0 -0
  28. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/foreign_omnibridge/build/ForeignOmnibridge.json +0 -0
  29. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/foreign_omnibridge/contract.py +0 -0
  30. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/foreign_omnibridge/contract.yaml +0 -0
  31. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/home_omnibridge/__init__.py +0 -0
  32. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/home_omnibridge/build/HomeOmnibridge.json +0 -0
  33. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/home_omnibridge/contract.py +0 -0
  34. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/home_omnibridge/contract.yaml +0 -0
  35. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l1_standard_bridge/__init__.py +0 -0
  36. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l1_standard_bridge/build/L1StandardBridge.json +0 -0
  37. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l1_standard_bridge/contract.py +0 -0
  38. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l1_standard_bridge/contract.yaml +0 -0
  39. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l2_standard_bridge/__init__.py +0 -0
  40. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l2_standard_bridge/build/L2StandardBridge.json +0 -0
  41. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l2_standard_bridge/contract.py +0 -0
  42. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/l2_standard_bridge/contract.yaml +0 -0
  43. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/mech_activity/__init__.py +0 -0
  44. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/mech_activity/build/MechActivity.json +0 -0
  45. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/mech_activity/contract.py +0 -0
  46. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/mech_activity/contract.yaml +0 -0
  47. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/optimism_mintable_erc20/__init__.py +0 -0
  48. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/optimism_mintable_erc20/build/OptimismMintableERC20.json +0 -0
  49. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/optimism_mintable_erc20/contract.py +0 -0
  50. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/optimism_mintable_erc20/contract.yaml +0 -0
  51. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/requester_activity_checker/__init__.py +0 -0
  52. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/requester_activity_checker/build/RequesterActivityChecker.json +0 -0
  53. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/requester_activity_checker/contract.py +0 -0
  54. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/requester_activity_checker/contract.yaml +0 -0
  55. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/staking_token/__init__.py +0 -0
  56. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/staking_token/build/StakingToken.json +0 -0
  57. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/staking_token/contract.py +0 -0
  58. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/staking_token/contract.yaml +0 -0
  59. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/__init__.py +0 -0
  60. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/build/IUniswapV2ERC20.json +0 -0
  61. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/contract.py +0 -0
  62. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/contract.yaml +0 -0
  63. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/tests/__init__.py +0 -0
  64. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py +0 -0
  65. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/keys.py +0 -0
  66. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/ledger/__init__.py +0 -0
  67. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/migration.py +0 -0
  68. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/operate_http/__init__.py +0 -0
  69. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/operate_http/exceptions.py +0 -0
  70. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/pearl.py +0 -0
  71. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/analyse_logs.py +0 -0
  72. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/claim_staking_rewards.py +0 -0
  73. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/reset_configs.py +0 -0
  74. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/reset_password.py +0 -0
  75. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/reset_staking.py +0 -0
  76. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/stop_service.py +0 -0
  77. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/terminate_on_chain_service.py +0 -0
  78. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/quickstart/utils.py +0 -0
  79. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/serialization.py +0 -0
  80. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/__init__.py +0 -0
  81. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/agent_runner.py +0 -0
  82. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/deployment_runner.py +0 -0
  83. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/funding_manager.py +0 -0
  84. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/health_checker.py +0 -0
  85. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/manage.py +0 -0
  86. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/protocol.py +0 -0
  87. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/utils/__init__.py +0 -0
  88. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/utils/mech.py +0 -0
  89. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/services/utils/tendermint.py +0 -0
  90. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/settings.py +0 -0
  91. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/utils/__init__.py +0 -0
  92. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/utils/gnosis.py +0 -0
  93. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/utils/single_instance.py +0 -0
  94. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/utils/ssl.py +0 -0
  95. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/wallet/__init__.py +0 -0
  96. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/wallet/master.py +0 -0
  97. {olas_operate_middleware-0.14.2 → olas_operate_middleware-0.14.3}/operate/wallet/wallet_recovery_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: olas-operate-middleware
3
- Version: 0.14.2
3
+ Version: 0.14.3
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: David Vilela
@@ -17,11 +17,11 @@ Requires-Dist: deepdiff (>=8.6.1,<9.0.0)
17
17
  Requires-Dist: fastapi (==0.110.3)
18
18
  Requires-Dist: halo (==0.0.31)
19
19
  Requires-Dist: multiaddr (==0.0.9)
20
- Requires-Dist: open-aea-cli-ipfs (>=2.0.6,<3.0.0)
21
- Requires-Dist: open-aea-ledger-cosmos (>=2.0.6,<3.0.0)
22
- Requires-Dist: open-aea-ledger-ethereum (>=2.0.6,<3.0.0)
23
- Requires-Dist: open-aea-ledger-ethereum-flashbots (>=2.0.6,<3.0.0)
24
- Requires-Dist: open-autonomy (>=0.21.5,<0.22.0)
20
+ Requires-Dist: open-aea-cli-ipfs (>=2.0.8,<3.0.0)
21
+ Requires-Dist: open-aea-ledger-cosmos (>=2.0.8,<3.0.0)
22
+ Requires-Dist: open-aea-ledger-ethereum (>=2.0.8,<3.0.0)
23
+ Requires-Dist: open-aea-ledger-ethereum-flashbots (>=2.0.8,<3.0.0)
24
+ Requires-Dist: open-autonomy (>=0.21.7,<0.22.0)
25
25
  Requires-Dist: psutil (>=5.9.8,<6.0.0)
26
26
  Requires-Dist: pyinstaller (>=6.8.0,<7.0.0)
27
27
  Requires-Dist: requests-mock (>=1.12.1,<2.0.0)
@@ -37,7 +37,7 @@ from types import FrameType
37
37
  import autonomy.chain.tx
38
38
  from aea.helpers.logging import setup_logger
39
39
  from clea import group, params, run
40
- from fastapi import FastAPI, Request
40
+ from fastapi import FastAPI, Query, Request
41
41
  from fastapi.middleware.cors import CORSMiddleware
42
42
  from fastapi.responses import JSONResponse
43
43
  from typing_extensions import Annotated
@@ -1066,6 +1066,68 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
1066
1066
  deployment_json["healthcheck"] = service.get_latest_healthcheck()
1067
1067
  return JSONResponse(content=deployment_json)
1068
1068
 
1069
+ @app.get("/api/v2/service/{service_config_id}/achievements")
1070
+ async def _get_service_achievements(
1071
+ request: Request, include_acknowledged: bool = Query(False) # noqa: B008
1072
+ ) -> JSONResponse:
1073
+ """Get the service achievements."""
1074
+ service_config_id = request.path_params["service_config_id"]
1075
+
1076
+ if not operate.service_manager().exists(service_config_id=service_config_id):
1077
+ return service_not_found_error(service_config_id=service_config_id)
1078
+
1079
+ service = operate.service_manager().load(service_config_id=service_config_id)
1080
+
1081
+ achievements_json = service.get_achievements_notifications(
1082
+ include_acknowledged=include_acknowledged,
1083
+ )
1084
+
1085
+ return JSONResponse(content=achievements_json)
1086
+
1087
+ @app.post(
1088
+ "/api/v2/service/{service_config_id}/achievement/{achievement_id}/acknowledge"
1089
+ )
1090
+ async def _acknowledge_achievement(request: Request) -> JSONResponse:
1091
+ """Update a service."""
1092
+ if operate.password is None:
1093
+ return USER_NOT_LOGGED_IN_ERROR
1094
+
1095
+ service_config_id = request.path_params["service_config_id"]
1096
+ manager = operate.service_manager()
1097
+
1098
+ if not manager.exists(service_config_id=service_config_id):
1099
+ return service_not_found_error(service_config_id=service_config_id)
1100
+
1101
+ service = operate.service_manager().load(service_config_id=service_config_id)
1102
+
1103
+ achievement_id = request.path_params["achievement_id"]
1104
+
1105
+ try:
1106
+ service.acknowledge_achievement(
1107
+ achievement_id=achievement_id,
1108
+ )
1109
+ except KeyError:
1110
+ return JSONResponse(
1111
+ content={
1112
+ "error": f"Achievement {achievement_id} does not exist for service {service_config_id}."
1113
+ },
1114
+ status_code=HTTPStatus.NOT_FOUND,
1115
+ )
1116
+ except ValueError:
1117
+ return JSONResponse(
1118
+ content={
1119
+ "error": f"Achievement {achievement_id} was already acknowledged for service {service_config_id}."
1120
+ },
1121
+ status_code=HTTPStatus.BAD_REQUEST,
1122
+ )
1123
+
1124
+ return JSONResponse(
1125
+ content={
1126
+ "error": None,
1127
+ "message": f"Acknowledged achievement_id {achievement_id} for service {service_config_id} successfully.",
1128
+ }
1129
+ )
1130
+
1069
1131
  @app.get("/api/v2/service/{service_config_id}/agent_performance")
1070
1132
  async def _get_agent_performance(request: Request) -> JSONResponse:
1071
1133
  """Get the service refill requirements."""
@@ -35,6 +35,7 @@ DEPLOYMENT_JSON = "deployment.json"
35
35
  CONFIG_JSON = "config.json"
36
36
  USER_JSON = "user.json"
37
37
  HEALTHCHECK_JSON = "healthcheck.json"
38
+ ACHIEVEMENTS_NOTIFICATIONS_JSON = "achievements_notifications.json"
38
39
  VERSION_FILE = "operate.version"
39
40
  SETTINGS_JSON = "settings.json"
40
41
  FUNDING_REQUIREMENTS_JSON = "funding_requirements.json"
@@ -102,6 +102,8 @@ STAKING: t.Dict[Chain, t.Dict[str, str]] = {
102
102
  "quickstart_beta_mech_marketplace_expert_8": "0x168aED532a0CD8868c22Fc77937Af78b363652B1",
103
103
  "quickstart_beta_mech_marketplace_expert_9": "0xdDa9cD214F12e7C2D58E871404A0A3B1177065C8",
104
104
  "quickstart_beta_mech_marketplace_expert_10": "0x53a38655B4e659eF4C7F88A26fbF5c67932C7156",
105
+ "quickstart_beta_mech_marketplace_expert_11": "0x1eaDe40561C61fa7AcC5D816b1FC55a8d9B58519",
106
+ "quickstart_beta_mech_marketplace_expert_12": "0x99Fe6B5C9980Fc3A44b1Dc32A76Db6aDfcf4c75e",
105
107
  "mech_marketplace": "0x998dEFafD094817EF329f6dc79c703f1CF18bC90",
106
108
  "marketplace_supply_alpha": "0xCAbD0C941E54147D40644CF7DA7e36d70DF46f44",
107
109
  "marketplace_demand_alpha_1": "0x9d6e7aB0B5B48aE5c146936147C639fEf4575231",
@@ -157,6 +159,10 @@ DEFAULT_PRIORITY_MECH = { # maps mech marketplace address to its default priori
157
159
  "0xC05e7412439bD7e91730a6880E18d5D5873F632C",
158
160
  2182,
159
161
  ),
162
+ "0x343F2B005cF6D70bA610CD9F1F1927049414B582": (
163
+ "0x45F25db135E83d7a010b05FFc1202F8473E3ae7D",
164
+ 25,
165
+ ),
160
166
  }
161
167
 
162
168
 
@@ -34,7 +34,11 @@ from autonomy.chain.config import LedgerType as LedgerTypeOA
34
34
  from cryptography.fernet import Fernet
35
35
  from typing_extensions import TypedDict
36
36
 
37
- from operate.constants import FERNET_KEY_LENGTH, NO_STAKING_PROGRAM_ID
37
+ from operate.constants import (
38
+ ACHIEVEMENTS_NOTIFICATIONS_JSON,
39
+ FERNET_KEY_LENGTH,
40
+ NO_STAKING_PROGRAM_ID,
41
+ )
38
42
  from operate.resource import LocalResource
39
43
  from operate.serialization import BigInt, serialize
40
44
 
@@ -220,6 +224,30 @@ class OnChainData(LocalResource):
220
224
  user_params: OnChainUserParams
221
225
 
222
226
 
227
+ @dataclass
228
+ class AchievementNotification(LocalResource):
229
+ """AchievementNotification"""
230
+
231
+ achievement_id: str
232
+ acknowledged: bool
233
+ acknowledgement_timestamp: int
234
+
235
+ @classmethod
236
+ def from_json(cls, obj: t.Dict) -> "ChainConfig":
237
+ """Load the chain config."""
238
+ return super().from_json(obj) # type: ignore
239
+
240
+
241
+ @dataclass
242
+ class AchievementsNotifications(LocalResource):
243
+ """AchievementsNotifications"""
244
+
245
+ path: Path
246
+ notifications: t.Dict[str, AchievementNotification]
247
+
248
+ _file = ACHIEVEMENTS_NOTIFICATIONS_JSON
249
+
250
+
223
251
  @dataclass
224
252
  class ChainConfig(LocalResource):
225
253
  """Chain config."""
@@ -109,6 +109,8 @@ QS_STAKING_PROGRAMS: t.Dict[Chain, t.Dict[str, str]] = {
109
109
  "quickstart_beta_mech_marketplace_expert_8": "trader",
110
110
  "quickstart_beta_mech_marketplace_expert_9": "trader",
111
111
  "quickstart_beta_mech_marketplace_expert_10": "trader",
112
+ "quickstart_beta_mech_marketplace_expert_11": "trader",
113
+ "quickstart_beta_mech_marketplace_expert_12": "trader",
112
114
  "mech_marketplace": "mech",
113
115
  "marketplace_supply_alpha": "mech",
114
116
  },
@@ -65,6 +65,16 @@ class LocalResource:
65
65
  kwargs[pname] = deserialize(obj=obj[pname], otype=ptype)
66
66
  return cls(**kwargs)
67
67
 
68
+ @classmethod
69
+ def exists_at(cls, path: Path) -> bool:
70
+ """Verifies if local resource exists at specified path."""
71
+ file = (
72
+ path / cls._file
73
+ if cls._file is not None and path.name != cls._file
74
+ else path
75
+ )
76
+ return file.exists()
77
+
68
78
  @classmethod
69
79
  def load(cls, path: Path) -> "LocalResource":
70
80
  """Load local resource."""
@@ -80,6 +80,8 @@ from operate.ledger import get_default_ledger_api, get_default_rpc
80
80
  from operate.ledger.profiles import WRAPPED_NATIVE_ASSET
81
81
  from operate.operate_http.exceptions import NotAllowed
82
82
  from operate.operate_types import (
83
+ AchievementNotification,
84
+ AchievementsNotifications,
83
85
  AgentRelease,
84
86
  Chain,
85
87
  ChainAmounts,
@@ -1028,13 +1030,107 @@ class Service(LocalResource):
1028
1030
  if isinstance(data, dict):
1029
1031
  agent_performance.update(data)
1030
1032
  except (json.JSONDecodeError, OSError) as e:
1031
- # Keep default values if file is invalid
1032
- print(
1033
- f"Error reading file 'agent_performance.json': {e}"
1034
- ) # TODO Use logger
1033
+ logger.warning(f"Cannot read file 'agent_performance.json': {e}")
1035
1034
 
1036
1035
  return dict(sorted(agent_performance.items()))
1037
1036
 
1037
+ def _load_achievements_notifications(
1038
+ self,
1039
+ ) -> t.Tuple[AchievementsNotifications, t.Dict[str, t.Any]]:
1040
+ if not AchievementsNotifications.exists_at(self.path):
1041
+ AchievementsNotifications(
1042
+ path=self.path,
1043
+ notifications={},
1044
+ ).store()
1045
+
1046
+ achievements_notifications: AchievementsNotifications = t.cast(
1047
+ AchievementsNotifications, AchievementsNotifications.load(self.path)
1048
+ )
1049
+
1050
+ agent_achievements_json_path = (
1051
+ Path(
1052
+ self.env_variables.get(
1053
+ AGENT_PERSISTENT_STORAGE_ENV_VAR, {"value": "."}
1054
+ ).get("value", ".")
1055
+ )
1056
+ / "achievements.json"
1057
+ )
1058
+
1059
+ agent_achievements: t.Dict[str, t.Any] = {}
1060
+ if agent_achievements_json_path.exists():
1061
+ try:
1062
+ with open(agent_achievements_json_path, "r", encoding="utf-8") as f:
1063
+ agent_achievements = json.load(f)
1064
+ except (json.JSONDecodeError, OSError) as e:
1065
+ print(f"Error reading file 'achievements.json': {e}")
1066
+
1067
+ save_changes = False
1068
+ for achievement_id in agent_achievements:
1069
+ if achievement_id not in achievements_notifications.notifications:
1070
+ achievements_notifications.notifications[achievement_id] = (
1071
+ AchievementNotification(
1072
+ achievement_id=achievement_id,
1073
+ acknowledged=False,
1074
+ acknowledgement_timestamp=0,
1075
+ )
1076
+ )
1077
+ save_changes = True
1078
+
1079
+ if save_changes:
1080
+ achievements_notifications.store()
1081
+
1082
+ return achievements_notifications, agent_achievements
1083
+
1084
+ def get_achievements_notifications(
1085
+ self, include_acknowledged: bool
1086
+ ) -> t.List[t.Dict]:
1087
+ """Return the achievements notifications"""
1088
+
1089
+ achievements_notifications, agent_achievements = (
1090
+ self._load_achievements_notifications()
1091
+ )
1092
+
1093
+ output: t.Dict[str, t.Dict] = {}
1094
+
1095
+ for (
1096
+ achievement_id,
1097
+ achievement_notification,
1098
+ ) in achievements_notifications.notifications.items():
1099
+ acknowledged = achievement_notification.acknowledged
1100
+ if not acknowledged or (acknowledged and include_acknowledged):
1101
+ if achievement_id in agent_achievements:
1102
+ output[achievement_id] = achievement_notification.json
1103
+ output[achievement_id].update(agent_achievements[achievement_id])
1104
+ else:
1105
+ logger.warning(
1106
+ f"Achievement {achievement_id} from notifications database is not present in agent achievements file (Corrupted file?)."
1107
+ )
1108
+
1109
+ return list(output.values())
1110
+
1111
+ def acknowledge_achievement(self, achievement_id: str) -> None:
1112
+ """Acknowledge an achievement id"""
1113
+
1114
+ achievements_notifications, _ = self._load_achievements_notifications()
1115
+
1116
+ if achievement_id not in achievements_notifications.notifications:
1117
+ raise KeyError(
1118
+ f"Achievement {achievement_id} does not exist for service {self.service_config_id}."
1119
+ )
1120
+
1121
+ achievement_notification = achievements_notifications.notifications[
1122
+ achievement_id
1123
+ ]
1124
+
1125
+ if achievement_notification.acknowledged:
1126
+ raise ValueError(
1127
+ f"Achievement {achievement_id} was already acknowledged for service {self.service_config_id}."
1128
+ )
1129
+
1130
+ achievement_notification.acknowledgement_timestamp = int(time.time())
1131
+ achievement_notification.acknowledged = True
1132
+ achievements_notifications.store()
1133
+
1038
1134
  def update(
1039
1135
  self,
1040
1136
  service_template: ServiceTemplate,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "olas-operate-middleware"
3
- version = "0.14.2"
3
+ version = "0.14.3"
4
4
  description = ""
5
5
  authors = ["David Vilela <dvilelaf@gmail.com>", "Viraj Patel <vptl185@gmail.com>"]
6
6
  readme = "README.md"
@@ -19,11 +19,11 @@ operate = "operate.cli:main"
19
19
 
20
20
  [tool.poetry.dependencies]
21
21
  python = "<3.12,>=3.10"
22
- open-autonomy = "^0.21.5"
23
- open-aea-ledger-cosmos = "^2.0.6"
24
- open-aea-ledger-ethereum = "^2.0.6"
25
- open-aea-ledger-ethereum-flashbots = "^2.0.6"
26
- open-aea-cli-ipfs = "^2.0.6"
22
+ open-autonomy = "^0.21.7"
23
+ open-aea-ledger-cosmos = "^2.0.8"
24
+ open-aea-ledger-ethereum = "^2.0.8"
25
+ open-aea-ledger-ethereum-flashbots = "^2.0.8"
26
+ open-aea-cli-ipfs = "^2.0.8"
27
27
  clea = "==0.1.0rc4"
28
28
  cytoolz = "==0.12.3"
29
29
  fastapi = "0.110.3"