olas-operate-middleware 0.6.3__py3-none-any.whl → 0.8.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.
operate/cli.py CHANGED
@@ -45,8 +45,15 @@ from uvicorn.server import Server
45
45
 
46
46
  from operate import services
47
47
  from operate.account.user import UserAccount
48
- from operate.bridge.bridge import BridgeManager
49
- from operate.constants import KEY, KEYS, OPERATE_HOME, SERVICES, ZERO_ADDRESS
48
+ from operate.bridge.bridge_manager import BridgeManager
49
+ from operate.constants import (
50
+ KEY,
51
+ KEYS,
52
+ MIN_PASSWORD_LENGTH,
53
+ OPERATE_HOME,
54
+ SERVICES,
55
+ ZERO_ADDRESS,
56
+ )
50
57
  from operate.ledger.profiles import (
51
58
  DEFAULT_MASTER_EOA_FUNDS,
52
59
  DEFAULT_NEW_SAFE_FUNDS,
@@ -68,12 +75,13 @@ from operate.utils.gnosis import get_assets_balances
68
75
  from operate.wallet.master import MasterWalletManager
69
76
 
70
77
 
71
- DEFAULT_HARDHAT_KEY = (
72
- "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
73
- ).encode()
74
78
  DEFAULT_MAX_RETRIES = 3
75
79
  USER_NOT_LOGGED_IN_ERROR = JSONResponse(
76
- content={"error": "User not logged in!"}, status_code=HTTPStatus.UNAUTHORIZED
80
+ content={"error": "User not logged in."}, status_code=HTTPStatus.UNAUTHORIZED
81
+ )
82
+ ACCOUNT_NOT_FOUND_ERROR = JSONResponse(
83
+ content={"error": "User account not found."},
84
+ status_code=HTTPStatus.NOT_FOUND,
77
85
  )
78
86
 
79
87
 
@@ -123,7 +131,7 @@ class OperateApp:
123
131
  """Updates current password"""
124
132
 
125
133
  if not new_password:
126
- raise ValueError("You must provide a new password.")
134
+ raise ValueError("'password' is required.")
127
135
 
128
136
  if not (
129
137
  self.user_account.is_valid(old_password)
@@ -140,7 +148,7 @@ class OperateApp:
140
148
  """Updates current password using the mnemonic"""
141
149
 
142
150
  if not new_password:
143
- raise ValueError("You must provide a new password.")
151
+ raise ValueError("'password' is required.")
144
152
 
145
153
  mnemonic = mnemonic.strip().lower()
146
154
  if not self.wallet_manager.is_mnemonic_valid(mnemonic):
@@ -345,30 +353,27 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
345
353
  """Call the endpoint."""
346
354
  logger.info(f"Calling `{f.__name__}` with retries enabled")
347
355
  retries = 0
348
- errors = []
349
356
  while retries < DEFAULT_MAX_RETRIES:
350
357
  try:
351
358
  return await f(request)
352
359
  except (APIError, ProjectError) as e:
353
360
  logger.error(f"Error {e}\n{traceback.format_exc()}")
354
- error = {"traceback": traceback.format_exc()}
355
- if "has active endpoints" in e.explanation:
356
- error["error"] = "Service is already running"
361
+ if "has active endpoints" in str(e):
362
+ error_msg = "Service is already running."
357
363
  else:
358
- error["error"] = str(e)
359
- errors.append(error)
364
+ error_msg = "Service deployment failed. Please check the logs."
360
365
  return JSONResponse(
361
- content={"errors": errors},
366
+ content={"error": error_msg},
362
367
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
363
368
  )
364
369
  except Exception as e: # pylint: disable=broad-except
365
- errors.append(
366
- {"error": str(e.args[0]), "traceback": traceback.format_exc()}
367
- )
368
- logger.error(f"Error {str(e.args[0])}\n{traceback.format_exc()}")
370
+ logger.error(f"Error {str(e)}\n{traceback.format_exc()}")
369
371
  retries += 1
370
372
  return JSONResponse(
371
- content={"errors": errors}, status_code=HTTPStatus.INTERNAL_SERVER_ERROR
373
+ content={
374
+ "error": "Operation failed after multiple attempts. Please try again later."
375
+ },
376
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
372
377
  )
373
378
 
374
379
  return _call
@@ -406,14 +411,20 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
406
411
  """Setup account."""
407
412
  if operate.user_account is not None:
408
413
  return JSONResponse(
409
- content={"error": "Account already exists"},
414
+ content={"error": "Account already exists."},
415
+ status_code=HTTPStatus.CONFLICT,
416
+ )
417
+
418
+ password = (await request.json()).get("password")
419
+ if not password or len(password) < MIN_PASSWORD_LENGTH:
420
+ return JSONResponse(
421
+ content={
422
+ "error": f"Password must be at least {MIN_PASSWORD_LENGTH} characters long."
423
+ },
410
424
  status_code=HTTPStatus.BAD_REQUEST,
411
425
  )
412
426
 
413
- data = await request.json()
414
- operate.create_user_account(
415
- password=data["password"],
416
- )
427
+ operate.create_user_account(password=password)
417
428
  return JSONResponse(content={"error": None})
418
429
 
419
430
  @app.put("/api/account")
@@ -423,10 +434,7 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
423
434
  ) -> t.Dict:
424
435
  """Update password."""
425
436
  if operate.user_account is None:
426
- return JSONResponse(
427
- content={"error": "Account does not exist."},
428
- status_code=HTTPStatus.BAD_REQUEST,
429
- )
437
+ return ACCOUNT_NOT_FOUND_ERROR
430
438
 
431
439
  data = await request.json()
432
440
  old_password = data.get("old_password")
@@ -436,7 +444,7 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
436
444
  if not old_password and not mnemonic:
437
445
  return JSONResponse(
438
446
  content={
439
- "error": "You must provide exactly one of 'old_password' or 'mnemonic' (seed phrase).",
447
+ "error": "Exactly one of 'old_password' or 'mnemonic' (seed phrase) is required.",
440
448
  },
441
449
  status_code=HTTPStatus.BAD_REQUEST,
442
450
  )
@@ -444,7 +452,15 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
444
452
  if old_password and mnemonic:
445
453
  return JSONResponse(
446
454
  content={
447
- "error": "You must provide exactly one of 'old_password' or 'mnemonic' (seed phrase), but not both.",
455
+ "error": "Exactly one of 'old_password' or 'mnemonic' (seed phrase) is required.",
456
+ },
457
+ status_code=HTTPStatus.BAD_REQUEST,
458
+ )
459
+
460
+ if not new_password or len(new_password) < MIN_PASSWORD_LENGTH:
461
+ return JSONResponse(
462
+ content={
463
+ "error": f"New password must be at least {MIN_PASSWORD_LENGTH} characters long."
448
464
  },
449
465
  status_code=HTTPStatus.BAD_REQUEST,
450
466
  )
@@ -453,27 +469,31 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
453
469
  if old_password:
454
470
  operate.update_password(old_password, new_password)
455
471
  return JSONResponse(
456
- content={"error": None, "message": "Password updated."}
472
+ content={"error": None, "message": "Password updated successfully."}
457
473
  )
458
474
  if mnemonic:
459
475
  operate.update_password_with_mnemonic(mnemonic, new_password)
460
476
  return JSONResponse(
461
477
  content={
462
478
  "error": None,
463
- "message": "Password updated using seed phrase.",
479
+ "message": "Password updated successfully using seed phrase.",
464
480
  }
465
481
  )
466
482
 
467
483
  return JSONResponse(
468
- content={"error": None, "message": "Password not updated."}
484
+ content={"error": "Password update failed."},
485
+ status_code=HTTPStatus.BAD_REQUEST,
469
486
  )
470
487
  except ValueError as e:
488
+ logger.error(f"Password update error: {e}\n{traceback.format_exc()}")
471
489
  return JSONResponse(
472
- content={"error": str(e)}, status_code=HTTPStatus.BAD_REQUEST
490
+ content={"error": f"Failed to update password: {str(e)}"},
491
+ status_code=HTTPStatus.BAD_REQUEST,
473
492
  )
474
493
  except Exception as e: # pylint: disable=broad-except
494
+ logger.error(f"Password update error: {e}\n{traceback.format_exc()}")
475
495
  return JSONResponse(
476
- content={"error": str(e), "traceback": traceback.format_exc()},
496
+ content={"error": "Failed to update password. Please check the logs."},
477
497
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
478
498
  )
479
499
 
@@ -482,21 +502,18 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
482
502
  async def _validate_password(request: Request) -> t.Dict:
483
503
  """Validate password."""
484
504
  if operate.user_account is None:
485
- return JSONResponse(
486
- content={"error": "Account does not exist"},
487
- status_code=HTTPStatus.BAD_REQUEST,
488
- )
505
+ return ACCOUNT_NOT_FOUND_ERROR
489
506
 
490
507
  data = await request.json()
491
508
  if not operate.user_account.is_valid(password=data["password"]):
492
509
  return JSONResponse(
493
- content={"error": "Password is not valid"},
510
+ content={"error": "Password is not valid."},
494
511
  status_code=HTTPStatus.UNAUTHORIZED,
495
512
  )
496
513
 
497
514
  operate.password = data["password"]
498
515
  return JSONResponse(
499
- content={"message": "Login successful"},
516
+ content={"message": "Login successful."},
500
517
  status_code=HTTPStatus.OK,
501
518
  )
502
519
 
@@ -514,16 +531,10 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
514
531
  async def _create_wallet(request: Request) -> t.List[t.Dict]:
515
532
  """Create wallet"""
516
533
  if operate.user_account is None:
517
- return JSONResponse(
518
- content={"error": "Cannot create wallet; User account does not exist!"},
519
- status_code=HTTPStatus.BAD_REQUEST,
520
- )
534
+ return ACCOUNT_NOT_FOUND_ERROR
521
535
 
522
536
  if operate.password is None:
523
- return JSONResponse(
524
- content={"error": "You need to login before creating a wallet"},
525
- status_code=HTTPStatus.UNAUTHORIZED,
526
- )
537
+ return USER_NOT_LOGGED_IN_ERROR
527
538
 
528
539
  data = await request.json()
529
540
  ledger_type = LedgerType(data["ledger_type"])
@@ -543,23 +554,15 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
543
554
  async def _get_private_key(request: Request) -> t.List[t.Dict]:
544
555
  """Get Master EOA private key."""
545
556
  if operate.user_account is None:
546
- return JSONResponse(
547
- content={
548
- "error": "Cannot retrieve private key; User account does not exist!"
549
- },
550
- status_code=HTTPStatus.BAD_REQUEST,
551
- )
557
+ return ACCOUNT_NOT_FOUND_ERROR
552
558
 
553
559
  data = await request.json()
554
560
  password = data.get("password")
555
- error = None
556
561
  if operate.password is None:
557
- error = {"error": "You need to login before retrieving the private key"}
562
+ return USER_NOT_LOGGED_IN_ERROR
558
563
  if operate.password != password:
559
- error = {"error": "Password is not valid"}
560
- if error is not None:
561
564
  return JSONResponse(
562
- content=error,
565
+ content={"error": "Password is not valid."},
563
566
  status_code=HTTPStatus.UNAUTHORIZED,
564
567
  )
565
568
 
@@ -597,12 +600,15 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
597
600
  manager = operate.wallet_manager
598
601
  if not manager.exists(ledger_type=ledger_type):
599
602
  return JSONResponse(
600
- content={"error": "Wallet does not exist"},
603
+ content={"error": "No Master EOA found for this chain."},
601
604
  status_code=HTTPStatus.NOT_FOUND,
602
605
  )
603
606
  safes = manager.load(ledger_type=ledger_type).safes
604
607
  if safes is None or safes.get(chain) is None:
605
- return JSONResponse(content={"error": "No safes found"})
608
+ return JSONResponse(
609
+ content={"error": "No Master Safe found for this chain."},
610
+ status_code=HTTPStatus.NOT_FOUND,
611
+ )
606
612
 
607
613
  return JSONResponse(
608
614
  content={
@@ -616,23 +622,17 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
616
622
  ) -> t.List[t.Dict]:
617
623
  """Create wallet safe"""
618
624
  if operate.user_account is None:
619
- return JSONResponse(
620
- content={"error": "Cannot create safe; User account does not exist!"},
621
- status_code=HTTPStatus.BAD_REQUEST,
622
- )
625
+ return ACCOUNT_NOT_FOUND_ERROR
623
626
 
624
627
  if operate.password is None:
625
- return JSONResponse(
626
- content={"error": "You need to login before creating a safe"},
627
- status_code=HTTPStatus.UNAUTHORIZED,
628
- )
628
+ return USER_NOT_LOGGED_IN_ERROR
629
629
 
630
630
  data = await request.json()
631
631
 
632
632
  if "initial_funds" in data and "transfer_excess_assets" in data:
633
633
  return JSONResponse(
634
634
  content={
635
- "error": "You can only specify 'initial_funds' or 'transfer_excess_assets', but not both."
635
+ "error": "Only specify one of 'initial_funds' or 'transfer_excess_assets', but not both."
636
636
  },
637
637
  status_code=HTTPStatus.BAD_REQUEST,
638
638
  )
@@ -643,14 +643,17 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
643
643
  ledger_type = chain.ledger_type
644
644
  manager = operate.wallet_manager
645
645
  if not manager.exists(ledger_type=ledger_type):
646
- return JSONResponse(content={"error": "Wallet does not exist"})
646
+ return JSONResponse(
647
+ content={"error": "No Master EOA found for this chain."},
648
+ status_code=HTTPStatus.NOT_FOUND,
649
+ )
647
650
 
648
651
  wallet = manager.load(ledger_type=ledger_type)
649
652
  if wallet.safes is not None and wallet.safes.get(chain) is not None:
650
653
  return JSONResponse(
651
654
  content={
652
655
  "safe": wallet.safes.get(chain),
653
- "message": f"Safe already exists {chain=}.",
656
+ "message": "Safe already exists for this chain.",
654
657
  }
655
658
  )
656
659
 
@@ -704,14 +707,15 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
704
707
  "create_tx": create_tx,
705
708
  "transfer_txs": transfer_txs,
706
709
  "safe": safes.get(chain),
707
- "message": "Safe created!",
708
- }
710
+ "message": "Safe created successfully",
711
+ },
712
+ status_code=HTTPStatus.CREATED,
709
713
  )
710
714
  except Exception as e: # pylint: disable=broad-except
711
- logger.error(traceback.format_exc())
715
+ logger.error(f"Safe creation failed: {e}\n{traceback.format_exc()}")
712
716
  return JSONResponse(
713
717
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
714
- content={"error": str(e), "traceback": traceback.format_exc()},
718
+ content={"error": "Failed to create safe. Please check the logs."},
715
719
  )
716
720
 
717
721
  @app.put("/api/wallet/safe")
@@ -720,22 +724,16 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
720
724
  """Update wallet safe"""
721
725
  # TODO: Extract login check as decorator
722
726
  if operate.user_account is None:
723
- return JSONResponse(
724
- content={"error": "Cannot update safe; User account does not exist!"},
725
- status_code=HTTPStatus.BAD_REQUEST,
726
- )
727
+ return ACCOUNT_NOT_FOUND_ERROR
727
728
 
728
729
  if operate.password is None:
729
- return JSONResponse(
730
- content={"error": "You need to login before updating a safe."},
731
- status_code=HTTPStatus.UNAUTHORIZED,
732
- )
730
+ return USER_NOT_LOGGED_IN_ERROR
733
731
 
734
732
  data = await request.json()
735
733
 
736
734
  if "chain" not in data:
737
735
  return JSONResponse(
738
- content={"error": "You need to specify a chain to update a safe."},
736
+ content={"error": "'chain' is required."},
739
737
  status_code=HTTPStatus.BAD_REQUEST,
740
738
  )
741
739
 
@@ -744,7 +742,7 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
744
742
  manager = operate.wallet_manager
745
743
  if not manager.exists(ledger_type=ledger_type):
746
744
  return JSONResponse(
747
- content={"error": "Wallet does not exist"},
745
+ content={"error": "No Master EOA found for this chain."},
748
746
  status_code=HTTPStatus.BAD_REQUEST,
749
747
  )
750
748
 
@@ -757,12 +755,12 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
757
755
 
758
756
  backup_owner_updated = wallet.update_backup_owner(
759
757
  chain=chain,
760
- backup_owner=backup_owner, # Optional value, it's fine to provide 'None' (set no backup owner/remove backup owner)
758
+ backup_owner=backup_owner,
761
759
  )
762
760
  message = (
763
- "Backup owner updated."
761
+ "Backup owner updated successfully"
764
762
  if backup_owner_updated
765
- else "No changes on backup owner. The backup owner provided matches the current one."
763
+ else "Backup owner is already set to this address"
766
764
  )
767
765
  return JSONResponse(
768
766
  content={
@@ -947,7 +945,7 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
947
945
  withdrawal_address = (await request.json()).get("withdrawal_address")
948
946
  if withdrawal_address is None:
949
947
  return JSONResponse(
950
- content={"error": "withdrawal_address is required"},
948
+ content={"error": "'withdrawal_address' is required"},
951
949
  status_code=HTTPStatus.BAD_REQUEST,
952
950
  )
953
951
 
@@ -989,13 +987,13 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
989
987
  from_safe=False,
990
988
  )
991
989
  except Exception as e: # pylint: disable=broad-except
992
- logger.error(traceback.format_exc())
990
+ logger.error(f"Withdrawal failed: {e}\n{traceback.format_exc()}")
993
991
  return JSONResponse(
994
992
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
995
- content={"error": str(e), "traceback": traceback.format_exc()},
993
+ content={"error": "Failed to withdraw funds. Please check the logs."},
996
994
  )
997
995
 
998
- return JSONResponse(content={"error": None})
996
+ return JSONResponse(content={"error": None, "message": "Withdrawal successful"})
999
997
 
1000
998
  @app.post("/api/bridge/bridge_refill_requirements")
1001
999
  @with_retries
@@ -1016,19 +1014,26 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
1016
1014
  status_code=HTTPStatus.OK,
1017
1015
  )
1018
1016
  except ValueError as e:
1017
+ logger.error(f"Bridge refill requirements error: {e}")
1019
1018
  return JSONResponse(
1020
- content={"error": str(e)}, status_code=HTTPStatus.BAD_REQUEST
1019
+ content={"error": "Invalid bridge request parameters."},
1020
+ status_code=HTTPStatus.BAD_REQUEST,
1021
1021
  )
1022
1022
  except Exception as e: # pylint: disable=broad-except
1023
+ logger.error(
1024
+ f"Bridge refill requirements error: {e}\n{traceback.format_exc()}"
1025
+ )
1023
1026
  return JSONResponse(
1024
- content={"error": str(e), "traceback": traceback.format_exc()},
1027
+ content={
1028
+ "error": "Failed to get bridge requirements. Please check the logs."
1029
+ },
1025
1030
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
1026
1031
  )
1027
1032
 
1028
1033
  @app.post("/api/bridge/execute")
1029
1034
  @with_retries
1030
1035
  async def _bridge_execute(request: Request) -> JSONResponse:
1031
- """Get the bridge refill requirements."""
1036
+ """Execute bridge transaction."""
1032
1037
  if operate.password is None:
1033
1038
  return USER_NOT_LOGGED_IN_ERROR
1034
1039
 
@@ -1041,12 +1046,17 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
1041
1046
  status_code=HTTPStatus.OK,
1042
1047
  )
1043
1048
  except ValueError as e:
1049
+ logger.error(f"Bridge execute error: {e}")
1044
1050
  return JSONResponse(
1045
- content={"error": str(e)}, status_code=HTTPStatus.BAD_REQUEST
1051
+ content={"error": "Invalid bundle ID or transaction failed."},
1052
+ status_code=HTTPStatus.BAD_REQUEST,
1046
1053
  )
1047
1054
  except Exception as e: # pylint: disable=broad-except
1055
+ logger.error(f"Bridge execute error: {e}\n{traceback.format_exc()}")
1048
1056
  return JSONResponse(
1049
- content={"error": str(e), "traceback": traceback.format_exc()},
1057
+ content={
1058
+ "error": "Failed to execute bridge transaction. Please check the logs."
1059
+ },
1050
1060
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
1051
1061
  )
1052
1062
 
@@ -1060,7 +1070,7 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
1060
1070
  @app.get("/api/bridge/status/{id}")
1061
1071
  @with_retries
1062
1072
  async def _bridge_status(request: Request) -> JSONResponse:
1063
- """Get the bridge refill requirements."""
1073
+ """Get bridge transaction status."""
1064
1074
 
1065
1075
  quote_bundle_id = request.path_params["id"]
1066
1076
 
@@ -1072,12 +1082,17 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st
1072
1082
  status_code=HTTPStatus.OK,
1073
1083
  )
1074
1084
  except ValueError as e:
1085
+ logger.error(f"Bridge status error: {e}")
1075
1086
  return JSONResponse(
1076
- content={"error": str(e)}, status_code=HTTPStatus.BAD_REQUEST
1087
+ content={"error": "Invalid bundle ID."},
1088
+ status_code=HTTPStatus.BAD_REQUEST,
1077
1089
  )
1078
1090
  except Exception as e: # pylint: disable=broad-except
1091
+ logger.error(f"Bridge status error: {e}\n{traceback.format_exc()}")
1079
1092
  return JSONResponse(
1080
- content={"error": str(e), "traceback": traceback.format_exc()},
1093
+ content={
1094
+ "error": "Failed to get bridge status. Please check the logs."
1095
+ },
1081
1096
  status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
1082
1097
  )
1083
1098
 
@@ -1093,20 +1108,35 @@ def _operate() -> None:
1093
1108
  def _daemon(
1094
1109
  host: Annotated[str, params.String(help="HTTP server host string")] = "localhost",
1095
1110
  port: Annotated[int, params.Integer(help="HTTP server port")] = 8000,
1111
+ ssl_keyfile: Annotated[str, params.String(help="Path to SSL key file")] = "",
1112
+ ssl_certfile: Annotated[
1113
+ str, params.String(help="Path to SSL certificate file")
1114
+ ] = "",
1096
1115
  home: Annotated[
1097
1116
  t.Optional[Path], params.Directory(long_flag="--home", help="Home directory")
1098
1117
  ] = None,
1099
1118
  ) -> None:
1100
1119
  """Launch operate daemon."""
1101
1120
  app = create_app(home=home)
1102
-
1103
- server = Server(
1104
- Config(
1105
- app=app,
1106
- host=host,
1107
- port=port,
1121
+ logger = setup_logger(name="daemon")
1122
+
1123
+ config_kwargs = {
1124
+ "app": app,
1125
+ "host": host,
1126
+ "port": port,
1127
+ }
1128
+
1129
+ # Use SSL certificates if ssl_keyfile and ssl_certfile are provided
1130
+ if ssl_keyfile and ssl_certfile:
1131
+ logger.info(f"Using SSL certificates: {ssl_certfile}")
1132
+ config_kwargs.update(
1133
+ {
1134
+ "ssl_keyfile": ssl_keyfile,
1135
+ "ssl_certfile": ssl_certfile,
1136
+ }
1108
1137
  )
1109
- )
1138
+
1139
+ server = Server(Config(**config_kwargs))
1110
1140
  app._server = server # pylint: disable=protected-access
1111
1141
  server.run()
1112
1142
 
operate/constants.py CHANGED
@@ -39,6 +39,7 @@ ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
39
39
  ON_CHAIN_INTERACT_TIMEOUT = 120.0
40
40
  ON_CHAIN_INTERACT_RETRIES = 10
41
41
  ON_CHAIN_INTERACT_SLEEP = 3.0
42
+ MIN_PASSWORD_LENGTH = 8
42
43
 
43
44
  HEALTH_CHECK_URL = "http://127.0.0.1:8716/healthcheck" # possible DNS issues on windows so use IP address
44
45
  SAFE_WEBAPP_URL = "https://app.safe.global/home?safe=gno:"
@@ -154,7 +154,17 @@ STAKING: t.Dict[Chain, t.Dict[str, str]] = {
154
154
  },
155
155
  }
156
156
 
157
- DEFAULT_MECH_MARKETPLACE_PRIORITY_MECH = "0x552cEA7Bc33CbBEb9f1D90c1D11D2C6daefFd053"
157
+
158
+ DEFAULT_PRIORITY_MECH = { # maps mech marketplace address to its default priority mech address and service id
159
+ "0x4554fE75c1f5576c1d7F765B2A036c199Adae329": (
160
+ "0x552cEA7Bc33CbBEb9f1D90c1D11D2C6daefFd053",
161
+ 975,
162
+ ),
163
+ "0x735FAAb1c4Ec41128c367AFb5c3baC73509f70bB": (
164
+ "0xC05e7412439bD7e91730a6880E18d5D5873F632C",
165
+ 2182,
166
+ ),
167
+ }
158
168
 
159
169
 
160
170
  # ERC20 token addresses
operate/operate_types.py CHANGED
@@ -329,3 +329,13 @@ class AssetFundingValues(TypedDict):
329
329
 
330
330
 
331
331
  FundingValues = t.Dict[str, AssetFundingValues] # str is the asset address
332
+
333
+
334
+ @dataclass
335
+ class MechMarketplaceConfig:
336
+ """Mech Marketplace config."""
337
+
338
+ use_mech_marketplace: bool
339
+ mech_marketplace_address: str
340
+ priority_mech_address: str
341
+ priority_mech_service_id: int
@@ -73,7 +73,7 @@ def claim_staking_rewards(operate: "OperateApp", config_path: str) -> None:
73
73
  config = configure_local_config(template, operate)
74
74
  manager = operate.service_manager()
75
75
  service = get_service(manager, template)
76
- ask_password_if_needed(operate, config)
76
+ ask_password_if_needed(operate)
77
77
 
78
78
  # reload manger and config after setting operate.password
79
79
  manager = operate.service_manager()
@@ -82,7 +82,7 @@ def reset_staking(operate: "OperateApp", config_path: str) -> None:
82
82
  print("Cancelled.")
83
83
  return
84
84
 
85
- ask_password_if_needed(operate, config)
85
+ ask_password_if_needed(operate)
86
86
  manager = operate.service_manager()
87
87
  service = get_service(manager, template)
88
88