olas-operate-middleware 0.13.1__py3-none-any.whl → 0.13.3__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.13.1.dist-info → olas_operate_middleware-0.13.3.dist-info}/METADATA +8 -27
- {olas_operate_middleware-0.13.1.dist-info → olas_operate_middleware-0.13.3.dist-info}/RECORD +42 -42
- operate/bridge/providers/provider.py +23 -31
- operate/cli.py +5 -18
- operate/constants.py +1 -0
- operate/data/contracts/dual_staking_token/contract.py +3 -3
- operate/data/contracts/dual_staking_token/contract.yaml +2 -2
- operate/data/contracts/foreign_omnibridge/contract.yaml +1 -1
- operate/data/contracts/home_omnibridge/contract.py +2 -2
- operate/data/contracts/home_omnibridge/contract.yaml +2 -2
- operate/data/contracts/l1_standard_bridge/contract.yaml +1 -1
- operate/data/contracts/l2_standard_bridge/contract.py +4 -4
- operate/data/contracts/l2_standard_bridge/contract.yaml +2 -2
- operate/data/contracts/mech_activity/contract.yaml +1 -1
- operate/data/contracts/optimism_mintable_erc20/contract.yaml +1 -1
- operate/data/contracts/recovery_module/contract.yaml +1 -1
- operate/data/contracts/requester_activity_checker/contract.yaml +1 -1
- operate/data/contracts/staking_token/contract.py +3 -3
- operate/data/contracts/staking_token/contract.yaml +2 -2
- operate/data/contracts/uniswap_v2_erc20/contract.yaml +3 -3
- operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py +5 -5
- operate/keys.py +5 -3
- operate/ledger/__init__.py +1 -7
- operate/ledger/profiles.py +0 -1
- operate/operate_http/__init__.py +0 -2
- operate/operate_types.py +3 -93
- operate/quickstart/run_service.py +63 -6
- operate/quickstart/utils.py +8 -4
- operate/resource.py +2 -2
- operate/services/agent_runner.py +3 -3
- operate/services/deployment_runner.py +107 -82
- operate/services/health_checker.py +38 -2
- operate/services/manage.py +14 -17
- operate/services/protocol.py +122 -141
- operate/services/utils/mech.py +3 -3
- operate/services/utils/tendermint.py +5 -3
- operate/utils/gnosis.py +76 -101
- operate/wallet/master.py +53 -50
- operate/wallet/wallet_recovery_manager.py +110 -56
- {olas_operate_middleware-0.13.1.dist-info → olas_operate_middleware-0.13.3.dist-info}/WHEEL +0 -0
- {olas_operate_middleware-0.13.1.dist-info → olas_operate_middleware-0.13.3.dist-info}/entry_points.txt +0 -0
- {olas_operate_middleware-0.13.1.dist-info → olas_operate_middleware-0.13.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
"""Wallet recovery manager"""
|
|
21
21
|
|
|
22
|
+
import enum
|
|
22
23
|
import shutil
|
|
23
24
|
import typing as t
|
|
24
25
|
import uuid
|
|
@@ -49,6 +50,19 @@ RECOVERY_NEW_OBJECTS_DIR = "new"
|
|
|
49
50
|
RECOVERY_OLD_OBJECTS_DIR = "old"
|
|
50
51
|
|
|
51
52
|
|
|
53
|
+
class WalletRecoveryStatus(str, enum.Enum):
|
|
54
|
+
"""ProviderRequestStatus"""
|
|
55
|
+
|
|
56
|
+
NOT_PREPARED = "NOT_PREPARED"
|
|
57
|
+
PREPARED = "PREPARED"
|
|
58
|
+
IN_PROGRESS = "IN_PROGRESS"
|
|
59
|
+
COMPLETED = "COMPLETED"
|
|
60
|
+
|
|
61
|
+
def __str__(self) -> str:
|
|
62
|
+
"""__str__"""
|
|
63
|
+
return self.value
|
|
64
|
+
|
|
65
|
+
|
|
52
66
|
class WalletRecoveryError(Exception):
|
|
53
67
|
"""WalletRecoveryError"""
|
|
54
68
|
|
|
@@ -125,20 +139,16 @@ class WalletRecoveryManager:
|
|
|
125
139
|
)
|
|
126
140
|
|
|
127
141
|
last_prepared_bundle_id = self.data.last_prepared_bundle_id
|
|
128
|
-
if
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
return self._load_bundle(
|
|
140
|
-
bundle_id=last_prepared_bundle_id, new_password=new_password
|
|
141
|
-
)
|
|
142
|
+
if (
|
|
143
|
+
last_prepared_bundle_id is not None
|
|
144
|
+
and self.status()["num_safes_with_new_wallet"] > 0
|
|
145
|
+
):
|
|
146
|
+
self.logger.info(
|
|
147
|
+
f"[WALLET RECOVERY MANAGER] Uncompleted bundle {last_prepared_bundle_id} has Safes with new wallet."
|
|
148
|
+
)
|
|
149
|
+
return self._load_bundle(
|
|
150
|
+
bundle_id=last_prepared_bundle_id, new_password=new_password
|
|
151
|
+
)
|
|
142
152
|
|
|
143
153
|
# Create new recovery bundle
|
|
144
154
|
bundle_id = f"{RECOVERY_BUNDLE_PREFIX}{str(uuid.uuid4())}"
|
|
@@ -178,23 +188,45 @@ class WalletRecoveryManager:
|
|
|
178
188
|
)
|
|
179
189
|
return self._load_bundle(bundle_id=bundle_id, new_password=new_password)
|
|
180
190
|
|
|
181
|
-
def
|
|
191
|
+
def _load_bundle( # pylint: disable=too-many-locals
|
|
192
|
+
self, bundle_id: str, new_password: t.Optional[str] = None
|
|
193
|
+
) -> t.Dict:
|
|
182
194
|
new_root = self.path / bundle_id / RECOVERY_NEW_OBJECTS_DIR
|
|
195
|
+
|
|
196
|
+
new_user_account = UserAccount.load(new_root / USER_JSON)
|
|
197
|
+
if new_password is not None and not new_user_account.is_valid(
|
|
198
|
+
password=new_password
|
|
199
|
+
):
|
|
200
|
+
raise ValueError(MSG_INVALID_PASSWORD)
|
|
201
|
+
|
|
183
202
|
new_wallets_path = new_root / WALLETS_DIR
|
|
184
|
-
new_wallet_manager = MasterWalletManager(
|
|
203
|
+
new_wallet_manager = MasterWalletManager(
|
|
204
|
+
path=new_wallets_path, password=new_password
|
|
205
|
+
)
|
|
185
206
|
|
|
186
207
|
num_safes = 0
|
|
187
208
|
num_safes_with_new_wallet = 0
|
|
188
209
|
num_safes_with_old_wallet = 0
|
|
189
210
|
num_safes_with_both_wallets = 0
|
|
211
|
+
backup_owner_sets = set()
|
|
190
212
|
|
|
213
|
+
wallets = []
|
|
191
214
|
for wallet in self.wallet_manager:
|
|
192
215
|
new_wallet = next(
|
|
193
216
|
(w for w in new_wallet_manager if w.ledger_type == wallet.ledger_type)
|
|
194
217
|
)
|
|
218
|
+
new_mnemonic = None
|
|
219
|
+
if new_password:
|
|
220
|
+
new_mnemonic = new_wallet.decrypt_mnemonic(password=new_password)
|
|
221
|
+
|
|
222
|
+
wallet_json = wallet.json
|
|
223
|
+
|
|
195
224
|
for chain, safe in wallet.safes.items():
|
|
225
|
+
chain_str = chain.value
|
|
196
226
|
ledger_api = get_default_ledger_api(chain)
|
|
197
227
|
owners = get_owners(ledger_api=ledger_api, safe=safe)
|
|
228
|
+
backup_owners = list(set(owners) - {wallet.address, new_wallet.address})
|
|
229
|
+
backup_owner_sets.add(frozenset(backup_owners))
|
|
198
230
|
|
|
199
231
|
num_safes += 1
|
|
200
232
|
if new_wallet.address in owners and wallet.address in owners:
|
|
@@ -204,42 +236,54 @@ class WalletRecoveryManager:
|
|
|
204
236
|
if wallet.address in owners:
|
|
205
237
|
num_safes_with_old_wallet += 1
|
|
206
238
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
new_wallets_path = new_root / WALLETS_DIR
|
|
222
|
-
new_wallet_manager = MasterWalletManager(
|
|
223
|
-
path=new_wallets_path, password=new_password
|
|
224
|
-
)
|
|
239
|
+
wallet_json["safes"][chain_str] = {
|
|
240
|
+
safe: {
|
|
241
|
+
"owners": owners,
|
|
242
|
+
"backup_owners": backup_owners,
|
|
243
|
+
"owner_to_remove": (
|
|
244
|
+
wallet.address if wallet.address in owners else None
|
|
245
|
+
),
|
|
246
|
+
"owner_to_add": (
|
|
247
|
+
new_wallet.address
|
|
248
|
+
if new_wallet.address not in owners
|
|
249
|
+
else None
|
|
250
|
+
),
|
|
251
|
+
}
|
|
252
|
+
}
|
|
225
253
|
|
|
226
|
-
wallets = []
|
|
227
|
-
for wallet in self.wallet_manager:
|
|
228
|
-
ledger_type = wallet.ledger_type
|
|
229
|
-
new_wallet = new_wallet_manager.load(ledger_type=ledger_type)
|
|
230
|
-
new_mnemonic = None
|
|
231
|
-
if new_password:
|
|
232
|
-
new_mnemonic = new_wallet.decrypt_mnemonic(password=new_password)
|
|
233
254
|
wallets.append(
|
|
234
255
|
{
|
|
235
|
-
"current_wallet":
|
|
256
|
+
"current_wallet": wallet_json,
|
|
236
257
|
"new_wallet": new_wallet.json,
|
|
237
258
|
"new_mnemonic": new_mnemonic,
|
|
238
259
|
}
|
|
239
260
|
)
|
|
261
|
+
|
|
262
|
+
if num_safes_with_new_wallet == 0:
|
|
263
|
+
status = WalletRecoveryStatus.PREPARED
|
|
264
|
+
elif num_safes_with_new_wallet < num_safes:
|
|
265
|
+
status = WalletRecoveryStatus.IN_PROGRESS
|
|
266
|
+
else:
|
|
267
|
+
status = WalletRecoveryStatus.COMPLETED
|
|
268
|
+
|
|
240
269
|
return {
|
|
241
270
|
"id": bundle_id,
|
|
242
271
|
"wallets": wallets,
|
|
272
|
+
"status": status,
|
|
273
|
+
"all_safes_have_backup_owner": all(
|
|
274
|
+
len(owners) >= 1 for owners in backup_owner_sets
|
|
275
|
+
),
|
|
276
|
+
"consistent_backup_owner": len(backup_owner_sets) == 1,
|
|
277
|
+
"consistent_backup_owner_count": all(
|
|
278
|
+
len(owners) == 1 for owners in backup_owner_sets
|
|
279
|
+
),
|
|
280
|
+
"prepared": bundle_id is not None,
|
|
281
|
+
"has_swaps": num_safes_with_new_wallet > 0,
|
|
282
|
+
"has_pending_swaps": num_safes_with_new_wallet < num_safes,
|
|
283
|
+
"num_safes": num_safes,
|
|
284
|
+
"num_safes_with_new_wallet": num_safes_with_new_wallet,
|
|
285
|
+
"num_safes_with_old_wallet": num_safes_with_old_wallet,
|
|
286
|
+
"num_safes_with_both_wallets": num_safes_with_both_wallets,
|
|
243
287
|
}
|
|
244
288
|
|
|
245
289
|
def recovery_requirements( # pylint: disable=too-many-locals
|
|
@@ -317,27 +361,37 @@ class WalletRecoveryManager:
|
|
|
317
361
|
def status(self) -> t.Dict[str, t.Any]:
|
|
318
362
|
"""Get recovery status."""
|
|
319
363
|
bundle_id = self.data.last_prepared_bundle_id
|
|
320
|
-
if
|
|
364
|
+
if bundle_id is None:
|
|
365
|
+
backup_owner_sets = set()
|
|
366
|
+
for wallet in self.wallet_manager:
|
|
367
|
+
for chain, safe in wallet.safes.items():
|
|
368
|
+
ledger_api = get_default_ledger_api(chain)
|
|
369
|
+
owners = get_owners(ledger_api=ledger_api, safe=safe)
|
|
370
|
+
backup_owners = list(set(owners) - {wallet.address})
|
|
371
|
+
backup_owner_sets.add(frozenset(backup_owners))
|
|
372
|
+
|
|
321
373
|
return {
|
|
374
|
+
"id": None,
|
|
375
|
+
"wallets": [],
|
|
376
|
+
"status": WalletRecoveryStatus.NOT_PREPARED,
|
|
377
|
+
"all_safes_have_backup_owner": all(
|
|
378
|
+
len(owners) >= 1 for owners in backup_owner_sets
|
|
379
|
+
),
|
|
380
|
+
"consistent_backup_owner": len(backup_owner_sets) == 1,
|
|
381
|
+
"consistent_backup_owner_count": all(
|
|
382
|
+
len(owners) == 1 for owners in backup_owner_sets
|
|
383
|
+
),
|
|
322
384
|
"prepared": False,
|
|
323
385
|
"bundle_id": bundle_id,
|
|
324
386
|
"has_swaps": False,
|
|
325
387
|
"has_pending_swaps": False,
|
|
388
|
+
"num_safes": 0,
|
|
389
|
+
"num_safes_with_new_wallet": 0,
|
|
390
|
+
"num_safes_with_old_wallet": 0,
|
|
391
|
+
"num_safes_with_both_wallets": 0,
|
|
326
392
|
}
|
|
327
393
|
|
|
328
|
-
(
|
|
329
|
-
num_safes,
|
|
330
|
-
num_safes_with_new_wallet,
|
|
331
|
-
_,
|
|
332
|
-
_,
|
|
333
|
-
) = self._get_swap_status(bundle_id)
|
|
334
|
-
|
|
335
|
-
return {
|
|
336
|
-
"prepared": bundle_id is not None,
|
|
337
|
-
"bundle_id": bundle_id,
|
|
338
|
-
"has_swaps": num_safes_with_new_wallet > 0,
|
|
339
|
-
"has_pending_swaps": num_safes_with_new_wallet < num_safes,
|
|
340
|
-
}
|
|
394
|
+
return self._load_bundle(bundle_id=bundle_id)
|
|
341
395
|
|
|
342
396
|
def complete_recovery( # pylint: disable=too-many-locals,too-many-statements
|
|
343
397
|
self, raise_if_inconsistent_owners: bool = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|