naeural-client 2.2.6__tar.gz → 2.3.1__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.
Files changed (132) hide show
  1. {naeural_client-2.2.6 → naeural_client-2.3.1}/PKG-INFO +5 -4
  2. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/_ver.py +1 -1
  3. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/generic_session.py +55 -11
  4. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base_decentra_object.py +8 -2
  5. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/bc/base.py +63 -7
  6. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/bc/ec.py +144 -1
  7. naeural_client-2.3.1/naeural_client/cli/README.md +7 -0
  8. naeural_client-2.3.1/naeural_client/cli/cli.py +48 -0
  9. naeural_client-2.3.1/naeural_client/cli/cli_commands.py +15 -0
  10. naeural_client-2.3.1/naeural_client/cli/nodes.py +22 -0
  11. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/base_logger.py +63 -27
  12. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/small_logger.py +2 -0
  13. naeural_client-2.3.1/naeural_client/utils/config.py +130 -0
  14. {naeural_client-2.2.6 → naeural_client-2.3.1}/pyproject.toml +10 -5
  15. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex01_part2_filter.py +4 -3
  16. naeural_client-2.3.1/xperimental/eth/eth_sign.py +74 -0
  17. naeural_client-2.3.1/xperimental/eth/info.md +0 -0
  18. {naeural_client-2.2.6 → naeural_client-2.3.1}/.devcontainer/Dockerfile +0 -0
  19. {naeural_client-2.2.6 → naeural_client-2.3.1}/.devcontainer/devcontainer.json +0 -0
  20. {naeural_client-2.2.6 → naeural_client-2.3.1}/.gitattributes +0 -0
  21. {naeural_client-2.2.6 → naeural_client-2.3.1}/.github/workflows/python-publish.yml +0 -0
  22. {naeural_client-2.2.6 → naeural_client-2.3.1}/.gitignore +0 -0
  23. {naeural_client-2.2.6 → naeural_client-2.3.1}/.vscode/launch.json +0 -0
  24. {naeural_client-2.2.6 → naeural_client-2.3.1}/LICENSE +0 -0
  25. {naeural_client-2.2.6 → naeural_client-2.3.1}/README.md +0 -0
  26. {naeural_client-2.2.6 → naeural_client-2.3.1}/TODOs.md +0 -0
  27. {naeural_client-2.2.6 → naeural_client-2.3.1}/__init__.py +0 -0
  28. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/__init__.py +0 -0
  29. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/__init__.py +0 -0
  30. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/distributed_custom_code_presets.py +0 -0
  31. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/instance.py +0 -0
  32. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/payload/__init__.py +0 -0
  33. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/payload/payload.py +0 -0
  34. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/pipeline.py +0 -0
  35. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/plugin_template.py +0 -0
  36. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/responses.py +0 -0
  37. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/base/transaction.py +0 -0
  38. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/bc/__init__.py +0 -0
  39. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/bc/chain.py +0 -0
  40. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/certs/__init__.py +0 -0
  41. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +0 -0
  42. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/code_cheker/__init__.py +0 -0
  43. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/code_cheker/base.py +0 -0
  44. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/code_cheker/checker.py +0 -0
  45. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/comm/__init__.py +0 -0
  46. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/comm/amqp_wrapper.py +0 -0
  47. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/comm/mqtt_wrapper.py +0 -0
  48. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/README.md +0 -0
  49. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/__init__.py +0 -0
  50. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/apps.py +0 -0
  51. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/base.py +0 -0
  52. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/comms.py +0 -0
  53. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/environment.py +0 -0
  54. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/formatter.py +0 -0
  55. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/heartbeat.py +0 -0
  56. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/misc.py +0 -0
  57. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/const/payload.py +0 -0
  58. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/__init__.py +0 -0
  59. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/__init__.py +0 -0
  60. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +0 -0
  61. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/custom_web_app_01_plugin.py +0 -0
  62. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/net_mon_01_plugin.py +0 -0
  63. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/telegram_basic_bot_01_plugin.py +0 -0
  64. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/telegram_conversational_bot_01_plugin.py +0 -0
  65. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/instance/view_scene_01_plugin.py +0 -0
  66. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/default/session/mqtt_session.py +0 -0
  67. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/__init__.py +0 -0
  68. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/base/__init__.py +0 -0
  69. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/base/base_formatter.py +0 -0
  70. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/default/__init__.py +0 -0
  71. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/default/a_dummy.py +0 -0
  72. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/default/aixp1.py +0 -0
  73. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/default/default.py +0 -0
  74. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/io_formatter/io_formatter_manager.py +0 -0
  75. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/__init__.py +0 -0
  76. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/__init__.py +0 -0
  77. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/class_instance_mixin.py +0 -0
  78. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/computer_vision_mixin.py +0 -0
  79. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/datetime_mixin.py +0 -0
  80. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/download_mixin.py +0 -0
  81. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/general_serialization_mixin.py +0 -0
  82. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/json_serialization_mixin.py +0 -0
  83. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +0 -0
  84. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/process_mixin.py +0 -0
  85. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/resource_size_mixin.py +0 -0
  86. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/timers_mixin.py +0 -0
  87. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/upload_mixin.py +0 -0
  88. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/logger_mixins/utils_mixin.py +0 -0
  89. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/tzlocal/__init__.py +0 -0
  90. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/tzlocal/unix.py +0 -0
  91. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/tzlocal/utils.py +0 -0
  92. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/tzlocal/win32.py +0 -0
  93. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/logging/tzlocal/windows_tz.py +0 -0
  94. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/plugins_manager_mixin.py +0 -0
  95. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/utils/__init__.py +0 -0
  96. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/utils/comm_utils.py +0 -0
  97. {naeural_client-2.2.6 → naeural_client-2.3.1}/naeural_client/utils/dotenv.py +0 -0
  98. {naeural_client-2.2.6 → naeural_client-2.3.1}/requirements.txt +0 -0
  99. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/.example_env +0 -0
  100. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/8. custom_code_fastapi_assets/index.html +0 -0
  101. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/9. code_sandbox_from_scratch_assets/index.html +0 -0
  102. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/_example_pk_sdk.pem +0 -0
  103. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex01_part1_connect.py +0 -0
  104. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex02_first_deploy.py +0 -0
  105. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex03_custom_code_on_one_remote__example_1.py +0 -0
  106. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex04_custom_code_on_one_remote__example_2.py +0 -0
  107. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex05_custom_code_on_one_remote__example_3.py +0 -0
  108. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex06_custom_code_on_multiple_remotes__example_1.py +0 -0
  109. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex07_custom_code_on_multiple_remotes__example_2.py +0 -0
  110. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex08_custom_web_app.py +0 -0
  111. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex09_code_sandbox_from_scratch.py +0 -0
  112. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex10_telegram_echo_bot.py +0 -0
  113. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex11_telegram_blackjack_bot.py +0 -0
  114. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/ex12_telegram_smart_bot.py +0 -0
  115. {naeural_client-2.2.6 → naeural_client-2.3.1}/tutorials/video_presentation/1. hello_world.ipynb +0 -0
  116. {naeural_client-2.2.6 → naeural_client-2.3.1}/winrun.bat +0 -0
  117. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/.example_env +0 -0
  118. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/README.md +0 -0
  119. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/_archive/test.py +0 -0
  120. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/_tutorials/3. simple_real_time_custom_code.py +0 -0
  121. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/_tutorials/4. real_time_custom_code_2.py +0 -0
  122. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/_tutorials/8. chatbot.py +0 -0
  123. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/attach_example.py +0 -0
  124. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/decentralized/chain_dist_example.py +0 -0
  125. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/decentralized/chain_dist_example_initiator.py +0 -0
  126. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/decentralized/chain_dist_example_worker.py +0 -0
  127. {naeural_client-2.2.6/xperimental → naeural_client-2.3.1/xperimental/enc_dec}/enc_dec_test.py +0 -0
  128. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/ex1.py +0 -0
  129. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/hello.py +0 -0
  130. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/remote_exec.py +0 -0
  131. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/save_images.py +0 -0
  132. {naeural_client-2.2.6 → naeural_client-2.3.1}/xperimental/utils/get_documentation.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: naeural_client
3
- Version: 2.2.6
3
+ Version: 2.3.1
4
4
  Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
5
- Project-URL: Homepage, https://github.com/Naeural Edge ProtocolEdgeProtocol/naeural_client
6
- Project-URL: Bug Tracker, https://github.com/Naeural Edge ProtocolEdgeProtocol/naeural_client/issues
7
- Author-email: Stefan Saraev <saraevstefan@gmail.com>, Andrei Ionut Damian <andrei.damian@me.com>, Cristan Bleotiu <cristibleotiu@gmail.com>
5
+ Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
6
+ Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
7
+ Author-email: Andrei Ionut Damian <andrei.damian@me.com>, Cristan Bleotiu <cristibleotiu@gmail.com>, Stefan Saraev <saraevstefan@gmail.com>
8
8
  Classifier: License :: OSI Approved :: MIT License
9
9
  Classifier: Operating System :: OS Independent
10
10
  Classifier: Programming Language :: Python :: 3
@@ -16,6 +16,7 @@ Requires-Dist: pika
16
16
  Requires-Dist: pyaml
17
17
  Requires-Dist: pyopenssl>=23.0.0
18
18
  Requires-Dist: python-dateutil
19
+ Requires-Dist: web3
19
20
  Description-Content-Type: text/markdown
20
21
 
21
22
  # naeural_client SDK
@@ -1,4 +1,4 @@
1
- __VER__ = "2.2.6"
1
+ __VER__ = "2.3.1"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  with open("pyproject.toml", "rt") as fd:
@@ -17,9 +17,12 @@ from ..utils import load_dotenv
17
17
  from .payload import Payload
18
18
  from .pipeline import Pipeline
19
19
  from .transaction import Transaction
20
+ from ..utils.config import load_user_defined_config, get_user_config_file
20
21
 
21
22
  # TODO: add support for remaining commands from EE
22
23
 
24
+ DEBUG_MQTT_SERVER = "r9092118.ala.eu-central-1.emqxsl.com"
25
+
23
26
 
24
27
  class GenericSession(BaseDecentrAIObject):
25
28
  """
@@ -59,7 +62,8 @@ class GenericSession(BaseDecentrAIObject):
59
62
  on_payload=None,
60
63
  on_notification=None,
61
64
  on_heartbeat=None,
62
- silent=True,
65
+ debug_silent=True,
66
+ silent=False,
63
67
  verbosity=1,
64
68
  dotenv_path=None,
65
69
  show_commands=False,
@@ -120,8 +124,14 @@ class GenericSession(BaseDecentrAIObject):
120
124
  Callback that handles heartbeats received from this network.
121
125
  As arguments, it has a reference to this Session object, the node name and the heartbeat payload.
122
126
  Defaults to None.
123
- silent : bool, optional
127
+
128
+ debug_silent : bool, optional
124
129
  This flag will disable debug logs, set to 'False` for a more verbose log, by default True
130
+
131
+ silent : bool, optional
132
+ This flag will disable all logs, set to 'False` for a more verbose log, by default False
133
+ The logs will still be recored in the log file even if this flag is set to True.
134
+
125
135
  dotenv_path : str, optional
126
136
  Path to the .env file, by default None. If None, the path will be searched in the current working directory and in the directories of the files from the call stack.
127
137
  root_topic : str, optional
@@ -142,6 +152,7 @@ class GenericSession(BaseDecentrAIObject):
142
152
 
143
153
  self.log = log
144
154
  self.name = name
155
+ self.silent = silent
145
156
 
146
157
  self._verbosity = verbosity
147
158
  self.encrypt_comms = encrypt_comms
@@ -158,7 +169,10 @@ class GenericSession(BaseDecentrAIObject):
158
169
  pwd = pwd or kwargs.get('password', kwargs.get('pass', None))
159
170
  user = user or kwargs.get('username', None)
160
171
  host = host or kwargs.get('hostname', None)
172
+
173
+ ## now we prepare config via ~/.naeural/config or .env
161
174
  self.__fill_config(host, port, user, pwd, secured, dotenv_path)
175
+ ## end config
162
176
 
163
177
  self.custom_on_payload = on_payload
164
178
  self.custom_on_heartbeat = on_heartbeat
@@ -180,15 +194,30 @@ class GenericSession(BaseDecentrAIObject):
180
194
  self.__open_transactions_lock = Lock()
181
195
 
182
196
  self.__create_user_callback_threads()
183
- super(GenericSession, self).__init__(log=log, DEBUG=not silent, create_logger=True)
197
+ super(GenericSession, self).__init__(
198
+ log=log,
199
+ DEBUG=not debug_silent,
200
+ create_logger=True,
201
+ silent=self.silent,
202
+ )
184
203
  return
185
204
 
186
205
  def startup(self):
187
- self.__start_blockchain(self.__bc_engine, self.__blockchain_config)
206
+ # start the blockchain engine assuming config is already set
207
+ self.__start_blockchain(
208
+ self.__bc_engine, self.__blockchain_config,
209
+ user_config=self.__user_config_loaded,
210
+ )
211
+ # end bc_engine
188
212
  self.formatter_wrapper = IOFormatterWrapper(self.log, plugin_search_locations=self.__formatter_plugins_locations)
189
213
 
190
214
  self._connect()
191
215
 
216
+ self.P("Created {} comms session '{}' from <{}> SDKv{}.".format(
217
+ "decrypted" if not self.encrypt_comms else "encrypted",
218
+ self.name, self.bc_engine.address, self.log.version
219
+ ))
220
+
192
221
  if not self.encrypt_comms:
193
222
  self.P(
194
223
  "Warning: Emitted messages will not be encrypted.\n"
@@ -546,7 +575,7 @@ class GenericSession(BaseDecentrAIObject):
546
575
 
547
576
  # Main loop
548
577
  if True:
549
- def __start_blockchain(self, bc_engine, blockchain_config):
578
+ def __start_blockchain(self, bc_engine, blockchain_config, user_config=False):
550
579
  if bc_engine is not None:
551
580
  self.bc_engine = bc_engine
552
581
  return
@@ -557,6 +586,7 @@ class GenericSession(BaseDecentrAIObject):
557
586
  name=self.name,
558
587
  config=blockchain_config,
559
588
  verbosity=self._verbosity,
589
+ user_config=user_config,
560
590
  )
561
591
  except:
562
592
  raise ValueError("Failure in private blockchain setup:\n{}".format(traceback.format_exc()))
@@ -780,15 +810,19 @@ class GenericSession(BaseDecentrAIObject):
780
810
  host : str
781
811
  The hostname of the server.
782
812
  Can be retrieved from the environment variables AIXP_HOSTNAME, AIXP_HOST
813
+
783
814
  port : int
784
815
  The port.
785
816
  Can be retrieved from the environment variable AIXP_PORT
817
+
786
818
  user : str
787
819
  The user name.
788
820
  Can be retrieved from the environment variables AIXP_USERNAME, AIXP_USER
821
+
789
822
  pwd : str
790
823
  The password.
791
824
  Can be retrieved from the environment variables AIXP_PASSWORD, AIXP_PASS, AIXP_PWD
825
+
792
826
  dotenv_path : str, optional
793
827
  Path to the .env file, by default None. If None, the path will be searched in the current working directory and in the directories of the files from the call stack.
794
828
 
@@ -798,11 +832,21 @@ class GenericSession(BaseDecentrAIObject):
798
832
  Missing credentials
799
833
  """
800
834
 
801
- # this method will search for the credentials in the environment variables
802
- # the path to env file, if not specified, will be search in the following order:
803
- # 1. current working directory
804
- # 2-N. directories of the files from the call stack
805
- load_dotenv(dotenv_path=dotenv_path, verbose=False)
835
+ # if the ~/.naeural/config file exists, load the credentials from there else try to load them from .env
836
+ if not load_user_defined_config():
837
+ # this method will search for the credentials in the environment variables
838
+ # the path to env file, if not specified, will be search in the following order:
839
+ # 1. current working directory
840
+ # 2-N. directories of the files from the call stack
841
+ load_dotenv(dotenv_path=dotenv_path, verbose=False)
842
+ if not self.silent:
843
+ print("Loaded credentials from environment variables.", flush=True)
844
+ self.__user_config_loaded = False
845
+ else:
846
+ if not self.silent:
847
+ print(f"Loaded credentials from `{get_user_config_file()}`.", flush=True)
848
+ self.__user_config_loaded = True
849
+ # endif config loading from ~ or ./.env
806
850
 
807
851
  possible_user_values = [
808
852
  user,
@@ -849,7 +893,7 @@ class GenericSession(BaseDecentrAIObject):
849
893
  os.getenv(ENVIRONMENT.EE_HOST),
850
894
  os.getenv(ENVIRONMENT.EE_MQTT_HOST),
851
895
  self._config.get(comm_ct.HOST),
852
- "r9092118.ala.eu-central-1.emqxsl.com",
896
+ DEBUG_MQTT_SERVER,
853
897
  ]
854
898
 
855
899
  host = next((x for x in possible_host_values if x is not None), None)
@@ -24,6 +24,7 @@ class BaseDecentrAIObject(object):
24
24
  show_prefixes=False,
25
25
  prefix_log=None,
26
26
  log_at_startup=False,
27
+ silent=False,
27
28
  **kwargs):
28
29
 
29
30
  super(BaseDecentrAIObject, self).__init__()
@@ -32,7 +33,13 @@ class BaseDecentrAIObject(object):
32
33
  if not create_logger:
33
34
  raise ValueError("Logger object is invalid: {}".format(log))
34
35
  else:
35
- log = Logger("DEF", DEBUG=DEBUG, base_folder='.', app_folder='_local_cache')
36
+ log = Logger(
37
+ "DEF",
38
+ DEBUG=DEBUG,
39
+ base_folder='.',
40
+ app_folder='_local_cache',
41
+ silent=silent,
42
+ )
36
43
  # endif
37
44
 
38
45
  self.log = log
@@ -79,7 +86,6 @@ class BaseDecentrAIObject(object):
79
86
  msg = "{} {}".format(self.prefix_log, s)
80
87
  # endif
81
88
  # endif
82
-
83
89
  _r = self.log.P(msg, show_time=t, color=color, **kwargs)
84
90
  return _r
85
91
 
@@ -12,6 +12,8 @@ from copy import deepcopy
12
12
 
13
13
  from cryptography.hazmat.primitives import serialization
14
14
 
15
+ from ..utils.config import get_user_folder
16
+
15
17
 
16
18
  class BCct:
17
19
  SIGN = 'EE_SIGN'
@@ -21,6 +23,7 @@ class BCct:
21
23
  ADDR_PREFIX_OLD = "aixp_"
22
24
  ADDR_PREFIX = "0xai_"
23
25
 
26
+ K_USER_CONFIG_PEM_FILE = 'NAEURAL_PEM_FILE'
24
27
  K_PEM_FILE = 'PEM_FILE'
25
28
  K_PASSWORD = 'PASSWORD'
26
29
  K_PEM_LOCATION = 'PEM_LOCATION'
@@ -270,7 +273,7 @@ class BaseBlockEngine:
270
273
  _lock: Lock = Lock()
271
274
  __instances = {}
272
275
 
273
- def __new__(cls, name, log, config, ensure_ascii_payloads=False, verbosity=1):
276
+ def __new__(cls, name, log, config, ensure_ascii_payloads=False, verbosity=1, user_config=False):
274
277
  with cls._lock:
275
278
  if name not in cls.__instances:
276
279
  instance = super(BaseBlockEngine, cls).__new__(cls)
@@ -278,6 +281,7 @@ class BaseBlockEngine:
278
281
  name=name, log=log, config=config,
279
282
  ensure_ascii_payloads=ensure_ascii_payloads,
280
283
  verbosity=verbosity,
284
+ user_config=user_config,
281
285
  )
282
286
  cls.__instances[name] = instance
283
287
  else:
@@ -291,6 +295,7 @@ class BaseBlockEngine:
291
295
  log=None,
292
296
  ensure_ascii_payloads=False,
293
297
  verbosity=1,
298
+ user_config=False,
294
299
  ):
295
300
 
296
301
  self.__name = name
@@ -304,11 +309,15 @@ class BaseBlockEngine:
304
309
  self.__config = config
305
310
  self.__ensure_ascii_payloads = ensure_ascii_payloads
306
311
 
307
- pem_name = config.get(BCct.K_PEM_FILE, '_pk.pem')
308
- pem_folder = config.get(BCct.K_PEM_LOCATION, 'data')
309
- pem_fn = os.path.join(log.get_target_folder(pem_folder), pem_name)
312
+ if user_config:
313
+ user_folder = get_user_folder()
314
+ pem_fn = str(user_folder / '_naeural.pem')
315
+ else:
316
+ pem_name = config.get(BCct.K_PEM_FILE, '_pk.pem')
317
+ pem_folder = config.get(BCct.K_PEM_LOCATION, 'data')
318
+ pem_fn = os.path.join(log.get_target_folder(pem_folder), pem_name)
319
+ #endif pem is defined in ~/.naeural/config
310
320
  self.__pem_file = pem_fn
311
-
312
321
  self._init()
313
322
  return
314
323
 
@@ -353,9 +362,13 @@ class BaseBlockEngine:
353
362
  password=self.__password,
354
363
  fn=self.__pem_file,
355
364
  )
356
- self.__public_key = self._get_pk(private_key=self.__private_key)
365
+ self.__public_key = self._get_pk(private_key=self.__private_key)
357
366
  self.__address = self._pk_to_address(self.__public_key)
358
- self.P("Current address: {}".format(self.address), boxed=True, verbosity=1)
367
+ ### Ethereum
368
+ self.__eth_address = self._get_eth_address()
369
+ self.__eth_account = self._get_eth_account()
370
+ ### end Ethereum
371
+ self.P("Address: {} / ETH: {}".format(self.address, self.eth_address), boxed=True, verbosity=1)
359
372
  self.P("Allowed list of senders: {}".format(self.allowed_list), verbosity=1)
360
373
  return
361
374
 
@@ -363,6 +376,11 @@ class BaseBlockEngine:
363
376
  def private_key(self):
364
377
  return self.__private_key
365
378
 
379
+
380
+ @property
381
+ def public_key(self):
382
+ return self.private_key.public_key()
383
+
366
384
 
367
385
  @staticmethod
368
386
  def _compute_hash(data : bytes, method='SHA256'):
@@ -717,6 +735,32 @@ class BaseBlockEngine:
717
735
 
718
736
  """
719
737
  raise NotImplementedError()
738
+
739
+
740
+ def _get_eth_address(self):
741
+ """
742
+ Returns the Ethereum address for the current pk
743
+
744
+ Returns
745
+ -------
746
+ eth_address : str
747
+ the Ethereum address.
748
+
749
+ """
750
+ raise NotImplementedError()
751
+
752
+
753
+ def _get_eth_acccount(self):
754
+ """
755
+ Returns the Ethereum account for the current sk
756
+
757
+ Returns
758
+ -------
759
+ eth_account : str
760
+ the Ethereum account.
761
+
762
+ """
763
+ raise NotImplementedError()
720
764
 
721
765
 
722
766
 
@@ -1045,3 +1089,15 @@ class BaseBlockEngine:
1045
1089
  """
1046
1090
  raise NotImplementedError()
1047
1091
 
1092
+
1093
+ ### Ethereum
1094
+
1095
+ @property
1096
+ def eth_address(self):
1097
+ return self.__eth_address
1098
+
1099
+ @property
1100
+ def eth_account(self):
1101
+ return self.__eth_account
1102
+
1103
+ ### end Ethereum
@@ -11,6 +11,11 @@ from cryptography.hazmat.backends import default_backend
11
11
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
12
12
  from cryptography.hazmat.primitives.kdf.hkdf import HKDF
13
13
 
14
+ from web3 import Web3
15
+ from eth_account import Account
16
+ from eth_utils import keccak, to_checksum_address
17
+ from eth_account.messages import encode_defunct
18
+
14
19
  from .base import BaseBlockEngine, VerifyMessage, BCct
15
20
 
16
21
 
@@ -18,6 +23,7 @@ from .base import BaseBlockEngine, VerifyMessage, BCct
18
23
  class BaseBCEllipticCurveEngine(BaseBlockEngine):
19
24
  MAX_ADDRESS_VALUE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
20
25
 
26
+
21
27
  def _get_pk(self, private_key : ec.EllipticCurvePrivateKey) -> ec.EllipticCurvePublicKey:
22
28
  """
23
29
  Simple wrapper to generate pk from sk
@@ -233,6 +239,7 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
233
239
  data=bpublic_key
234
240
  )
235
241
  return public_key
242
+
236
243
 
237
244
  def __derive_shared_key(self, peer_public_key : str, info : str = BCct.DEFAULT_INFO, debug : bool = False):
238
245
  """
@@ -266,6 +273,7 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
266
273
  if debug:
267
274
  print('derived-shared_key: ', base64.b64encode(derived_key))
268
275
  return derived_key
276
+
269
277
 
270
278
  def encrypt(
271
279
  self,
@@ -380,5 +388,140 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
380
388
 
381
389
  result = plaintext.decode()
382
390
  except Exception as exc:
391
+ if debug:
392
+ self.P("Error decrypting from <{}> (compressed_flag `{}`): {}".format(
393
+ sender_address, compressed_flag, exc), color='r'
394
+ )
383
395
  result = None
384
- return result
396
+ return result
397
+
398
+
399
+
400
+ ### ETH
401
+
402
+ def _get_eth_address(self, pk=None):
403
+ if pk is None:
404
+ pk = self.public_key
405
+ raw_public_key = pk.public_numbers()
406
+
407
+ # Compute Ethereum-compatible address
408
+ x = raw_public_key.x.to_bytes(32, 'big')
409
+ y = raw_public_key.y.to_bytes(32, 'big')
410
+ uncompressed_key = b'\x04' + x + y
411
+ keccak_hash = keccak(uncompressed_key[1:]) # Remove 0x04 prefix
412
+ eth_address = "0x" + keccak_hash[-20:].hex()
413
+ eth_address = to_checksum_address(eth_address)
414
+ return eth_address
415
+
416
+ def _get_eth_account(self):
417
+ private_key_bytes = self.private_key.private_numbers().private_value.to_bytes(32, 'big')
418
+ return Account.from_key(private_key_bytes)
419
+
420
+
421
+ def node_address_to_eth_address(self, address):
422
+ """
423
+ Converts a node address to an Ethereum address.
424
+
425
+ Parameters
426
+ ----------
427
+ address : str
428
+ The node address convert.
429
+
430
+ Returns
431
+ -------
432
+ str
433
+ The Ethereum address.
434
+ """
435
+ public_key = self._address_to_pk(address)
436
+ return self._get_eth_address(pk=public_key)
437
+
438
+
439
+
440
+ def eth_hash_message(self, types, values, as_hex=False):
441
+ """
442
+ Hashes a message using the keccak256 algorithm.
443
+
444
+ Parameters
445
+ ----------
446
+ types : list
447
+ The types of the values.
448
+
449
+ values : list of any
450
+ The values to hash.
451
+
452
+ Returns
453
+ -------
454
+ bytes
455
+ The hash of the message in hexadecimal format.
456
+ """
457
+ message = Web3.solidity_keccak(types, values)
458
+ if as_hex:
459
+ return message.hex()
460
+ return message
461
+
462
+
463
+ def eth_sign_message(self, types, values):
464
+ """
465
+ Signs a message using the private key.
466
+
467
+ Parameters
468
+ ----------
469
+ types : list
470
+ The types of the values.
471
+
472
+ values : list of any
473
+ The values to sign.
474
+
475
+ Returns
476
+ -------
477
+ str
478
+ The signature of the message.
479
+ """
480
+ message_hash = self.eth_hash_message(types, values, as_hex=False)
481
+ signable_message = encode_defunct(primitive=message_hash)
482
+ signed_message = Account.sign_message(signable_message, private_key=self.eth_account.key)
483
+ if hasattr(signed_message, "message_hash"): # backward compatibility
484
+ signed_message_hash = signed_message.message_hash
485
+ else:
486
+ signed_message_hash = signed_message.messageHash
487
+ return {
488
+ "message_hash": message_hash.hex(),
489
+ "r": hex(signed_message.r),
490
+ "s": hex(signed_message.s),
491
+ "v": signed_message.v,
492
+ "signature": signed_message.signature.hex(),
493
+ "signed_message": signed_message_hash.hex(),
494
+ "sender" : self.eth_address,
495
+ }
496
+
497
+ def eth_sign_node_epochs(self, node, epochs, epochs_vals, signature_only=True):
498
+ """
499
+ Signs the node availability
500
+
501
+ Parameters
502
+ ----------
503
+ node : str
504
+ The node address.
505
+
506
+ epochs : list of int
507
+ The epochs to sign.
508
+
509
+ epochs_vals : list of int
510
+ The values for each epoch.
511
+
512
+ signature_only : bool, optional
513
+ Whether to return only the signature. The default is True.
514
+
515
+ Returns
516
+ -------
517
+ str
518
+ The signature of the message.
519
+ """
520
+ types = ["string", "uint256[]", "uint256[]"]
521
+ values = [node, epochs, epochs_vals]
522
+ result = self.eth_sign_message(types, values)
523
+ if signature_only:
524
+ return result["signature"]
525
+ return result
526
+
527
+
@@ -0,0 +1,7 @@
1
+ # The Naeural Edge Protocol CLI
2
+
3
+ ## Develop
4
+
5
+ ```bash
6
+ pip install -e .
7
+ ```
@@ -0,0 +1,48 @@
1
+ import argparse
2
+
3
+ from naeural_client.utils.config import maybe_init_config, log_with_color
4
+ from naeural_client.cli.cli_commands import CLI_COMMANDS
5
+
6
+ from naeural_client import version
7
+
8
+ def build_parser():
9
+ """
10
+ Dynamically builds the argument parser based on CLI_COMMANDS.
11
+
12
+ Returns
13
+ -------
14
+ argparse.ArgumentParser
15
+ Configured argument parser.
16
+ """
17
+ descr = f"nepctl v{version} - CLI for Naeural Edge Protocol SDK package"
18
+
19
+
20
+ parser = argparse.ArgumentParser(description=descr)
21
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
22
+
23
+ # Iterate over top-level commands
24
+ for command, subcommands in CLI_COMMANDS.items():
25
+ command_parser = subparsers.add_parser(command, help=f"{command} commands")
26
+ if isinstance(subcommands, dict): # Nested subcommands
27
+ command_subparsers = command_parser.add_subparsers(dest="subcommand")
28
+ for subcommand, func in subcommands.items():
29
+ subcommand_parser = command_subparsers.add_parser(
30
+ subcommand, help=f"{subcommand} command"
31
+ )
32
+ subcommand_parser.set_defaults(func=func)
33
+ else:
34
+ command_parser.set_defaults(func=subcommands)
35
+
36
+ return parser
37
+
38
+ def main():
39
+ maybe_init_config()
40
+ parser = build_parser()
41
+ args = parser.parse_args()
42
+ if hasattr(args, "func"):
43
+ args.func() # Call the dynamically loaded function
44
+ else:
45
+ parser.print_help()
46
+
47
+ if __name__ == "__main__":
48
+ main()
@@ -0,0 +1,15 @@
1
+ from naeural_client.cli.nodes import get_nodes, get_supervisors
2
+ from naeural_client.utils.config import show_config, reset_config
3
+
4
+
5
+ # Define the available commands
6
+ CLI_COMMANDS = {
7
+ "get": {
8
+ "nodes": get_nodes,
9
+ "supervisors": get_supervisors,
10
+ },
11
+ "config": {
12
+ "show": show_config,
13
+ "reset": reset_config,
14
+ },
15
+ }
@@ -0,0 +1,22 @@
1
+ from naeural_client.utils.config import log_with_color
2
+
3
+
4
+ def get_nodes():
5
+ """
6
+ This function is used to get the information about the nodes and it will perform the following:
7
+
8
+ 1. Create a Session object.
9
+ 2. Wait for the first net mon message via Session and show progress.
10
+ 3. Wait for the second net mon message via Session and show progress.
11
+ 4. Get the active nodes union via Session and display the nodes marking those peered vs non-peered.
12
+ """
13
+ log_with_color("Getting nodes information", color="b")
14
+ return
15
+
16
+
17
+ def get_supervisors():
18
+ """
19
+ This function is used to get the information about the supervisors.
20
+ """
21
+ log_with_color("Getting supervisors information", color='b')
22
+ return