neuronum 7.0.3__py3-none-any.whl → 8.0.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.

Potentially problematic release.


This version of neuronum might be problematic. Click here for more details.

cli/main.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import subprocess
2
2
  import os
3
- import neuronum
4
3
  import platform
5
4
  import glob
6
5
  import asyncio
@@ -12,7 +11,9 @@ import requests
12
11
  import psutil
13
12
  from datetime import datetime
14
13
  import sys
15
-
14
+ import json
15
+ from cryptography.hazmat.primitives.asymmetric import ec
16
+ from cryptography.hazmat.primitives import serialization
16
17
 
17
18
  @click.group()
18
19
  def cli():
@@ -223,6 +224,7 @@ def delete_cell():
223
224
  return
224
225
 
225
226
  confirm = click.confirm(f" Are you sure you want to delete '{host}'?", default=True)
227
+ os.remove(env_path)
226
228
  if not confirm:
227
229
  click.echo("Deletion canceled.")
228
230
  return
@@ -268,18 +270,12 @@ async def async_init_node(descr):
268
270
  key, value = line.strip().split("=")
269
271
  env_data[key] = value
270
272
 
273
+
271
274
  host = env_data.get("HOST", "")
272
275
  password = env_data.get("PASSWORD", "")
273
276
  network = env_data.get("NETWORK", "")
274
277
  synapse = env_data.get("SYNAPSE", "")
275
278
 
276
- cell = neuronum.Cell(
277
- host=host,
278
- password=password,
279
- network=network,
280
- synapse=synapse
281
- )
282
-
283
279
  except FileNotFoundError:
284
280
  click.echo("No cell connected. Connect your cell with command neuronum connect-cell")
285
281
  return
@@ -300,87 +296,84 @@ async def async_init_node(descr):
300
296
  async with session.post(url, json=node) as response:
301
297
  response.raise_for_status()
302
298
  data = await response.json()
303
- nodeID = data["nodeID"]
299
+ node_id = data["nodeID"]
304
300
  except aiohttp.ClientError as e:
305
301
  click.echo(f"Error sending request: {e}")
306
302
  return
307
303
 
308
- node_filename = descr + "_" + nodeID.replace("::node", "")
304
+ node_filename = descr + "_" + node_id.replace("::node", "")
309
305
  project_path = Path(node_filename)
310
306
  project_path.mkdir(exist_ok=True)
311
307
 
312
- env_path = project_path / ".env"
313
- await asyncio.to_thread(env_path.write_text, f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
308
+ try:
309
+ private_key = ec.generate_private_key(ec.SECP256R1())
310
+ public_key = private_key.public_key()
314
311
 
315
- stx_descr = f"{nodeID} App"
316
- partners = ["private"]
317
- stxID = await cell.create_stx(stx_descr, partners)
312
+ pem_private = private_key.private_bytes(
313
+ encoding=serialization.Encoding.PEM,
314
+ format=serialization.PrivateFormat.PKCS8,
315
+ encryption_algorithm=serialization.NoEncryption()
316
+ )
318
317
 
319
- tx_descr = f"Greet {nodeID}"
320
- key_values = {
321
- "ping": "pong",
322
- }
323
- STX = stxID
324
- label = "ping:pong"
325
- partners = ["private"]
326
- txID = await cell.create_tx(tx_descr, key_values, STX, label, partners)
318
+ pem_public = public_key.public_bytes(
319
+ encoding=serialization.Encoding.PEM,
320
+ format=serialization.PublicFormat.SubjectPublicKeyInfo
321
+ )
322
+
323
+ public_key_pem_file = project_path / "public_key.pem"
324
+ with open(public_key_pem_file, "wb") as key_file:
325
+ key_file.write(pem_public)
327
326
 
327
+ private_key_pem_file = project_path / "private_key.pem"
328
+ with open(private_key_pem_file, "wb") as key_file:
329
+ key_file.write(pem_private)
330
+
331
+ pem_public_str = pem_public.decode('utf-8')
332
+ pem_public_oneline = "".join(pem_public_str.split())
333
+
334
+ current_directory = os.getcwd()
335
+ private_key_file = os.path.join(current_directory / project_path, "private_key.pem")
336
+ public_key_file = os.path.join(current_directory / project_path, "public_key.pem")
337
+ except:
338
+ print("Error creating Private/Public Key Pair")
339
+
328
340
  app_path = project_path / "app.py"
329
341
  app_path.write_text(f"""\
330
342
  import asyncio
331
- import neuronum
332
- import os
333
- import json
334
- from dotenv import load_dotenv
335
- from jinja2 import Environment, FileSystemLoader
336
-
343
+ import neuronum
344
+ from jinja2 import Environment, FileSystemLoader
345
+
337
346
  env = Environment(loader=FileSystemLoader('.'))
338
347
  template = env.get_template('ping.html')
339
-
340
- with open('config.json', 'r') as f:
341
- data = json.load(f)
342
- terms_url = data['legals']['terms']
343
- privacy_url = data['legals']['privacy_policy']
344
- last_update = data['legals']['last_update']
345
-
346
-
347
- load_dotenv()
348
- host = os.getenv("HOST")
349
- password = os.getenv("PASSWORD")
350
- network = os.getenv("NETWORK")
351
- synapse = os.getenv("SYNAPSE")
352
-
348
+
353
349
  cell = neuronum.Cell(
354
- host=host,
355
- password=password,
356
- network=network,
357
- synapse=synapse
350
+ private_key_path="{private_key_file}",
351
+ public_key_path="{public_key_file}"
358
352
  )
359
-
360
- async def main():
361
- STX = "{stxID}"
362
- async for operation in cell.sync(STX):
363
- txID = operation.get("txID")
364
- client = operation.get("operator")
365
- ts = operation.get("time")
366
- data = operation.get("data")
367
- operation_id = operation.get("operationID")
368
-
369
- if txID == "{txID}":
353
+
354
+ async def main():
355
+
356
+ node_id = "{node_id}"
357
+ async for transmitter in cell.sync(node_id):
358
+ ts = transmitter.get("time")
359
+ data = transmitter.get("data")
360
+ transmitter_id = transmitter.get("transmitter_id")
361
+ client = transmitter.get("operator")
362
+ client_public_key = data.get("publicKey")
363
+ action = data.get("action")
364
+
365
+ response_data = {{}}
366
+
367
+ if action == "ping_node":
370
368
 
371
- def render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update):
372
- return template.render(client=client, ts=ts, data=data, operation_id=operation_id, terms_url=terms_url, privacy_url=privacy_url, last_update=last_update)
373
-
374
- html_content = render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update)
369
+ html_content = template.render(client=client, ts=ts, data=action, transmitter_id=transmitter_id)
375
370
 
376
- data = {{
377
- "json": f"{{operation_id}} - Reply from {nodeID}: Pinged by {{client}} at {{ts}} with data: {{data}}",
371
+ response_data = {{
372
+ "json": f"{{transmitter_id}} - Reply from {node_id}: Pinged by {{client}} at {{ts}} with action: {{action}}",
378
373
  "html": html_content
379
374
  }}
380
-
381
- await cell.notify(f"{{client}}", "{nodeID} Ping","Pinged successfully")
382
-
383
- await cell.tx_response(txID, client, data)
375
+
376
+ await cell.tx_response(transmitter_id, response_data, client_public_key)
384
377
 
385
378
  asyncio.run(main())
386
379
  """)
@@ -468,7 +461,7 @@ asyncio.run(main())
468
461
  .data-value.timestamp {{
469
462
  color: #a1e8a1;
470
463
  }}
471
- .data-value.operation-id {{
464
+ .data-value.transmitter-id {{
472
465
  color: #f7a2a2;
473
466
  }}
474
467
  .api-button {{
@@ -489,7 +482,7 @@ asyncio.run(main())
489
482
  <div class="container">
490
483
  <img class="logo" src="https://neuronum.net/static/logo.png" alt="Neuronum Logo">
491
484
 
492
- <h1>Reply from {nodeID}</h1>
485
+ <h1>Reply from {node_id}</h1>
493
486
  <p class="subtitle">Pinged successfully.</p>
494
487
 
495
488
  <div class="data-row">
@@ -508,157 +501,61 @@ asyncio.run(main())
508
501
  </div>
509
502
 
510
503
  <div class="data-row">
511
- <p class="data-label">Operation ID</p>
512
- <p class="data-value operation-id truncated">{{{{operation_id}}}}</p>
504
+ <p class="data-label">Transmitter ID</p>
505
+ <p class="data-value transmitter-id truncated">{{{{transmitter_id}}}}</p>
513
506
  </div>
514
507
 
515
508
  <button id="send-request-btn" class="api-button">Ping again</button>
516
509
  </div>
517
510
 
518
511
  <script>
519
- document.getElementById('send-request-btn').addEventListener('click', () => {{
520
- const apiEndpoint = 'https://neuronum.net/api/activate/{txID}';
521
-
522
- const dataToSend = {{
523
- "data": {{"ping": "node"}},
524
- "cell": {{
525
- "host": CLIENT_CELL,
526
- "session": CLIENT_SESSION,
527
- }}
528
- }};
529
-
530
- fetch(apiEndpoint, {{
531
- method: 'POST',
532
- headers: {{
533
- 'Content-Type': 'application/json',
534
- 'Accept': 'application/json'
535
- }},
536
- body: JSON.stringify(dataToSend)
537
- }})
538
- .then(response => {{
539
- if (!response.ok) {{
540
- throw new Error(`HTTP error! status: ${{response.status}}`);
512
+ document.getElementById('send-request-btn').addEventListener('click', () => {{
513
+ const messagePayload = {{
514
+ type: 'iframe_request',
515
+ endpoint: 'https://neuronum.net/browser/api/activate_tx/{node_id}',
516
+ data: {{ "action": "ping_node" }},
517
+ nodePublicKey: '{pem_public_oneline}',
518
+ }};
519
+
520
+ if (window.parent) {{
521
+ window.parent.postMessage(messagePayload, '*');
541
522
  }}
542
- return response.json();
543
- }})
544
- .then(data => {{
545
- if (data.success && data.response && data.response.html) {{
546
- document.open();
547
- document.write(data.response.html);
548
- document.close();
549
- console.log('API Response: Page replaced with new HTML.');
550
- }} else {{
551
- console.error('API Response does not contain HTML to replace the page:', data);
552
- alert('API response error: Expected HTML content to replace the page.');
553
- }}
554
- }})
555
- .catch(error => {{
556
- console.error('API request failed:', error);
557
- alert('API request failed. See the console for details.');
558
523
  }});
559
- }});
560
- </script>
561
-
562
- <div id="legal-banner" style="border-radius: 10px; margin: 15px; position: fixed; bottom: 0; left: 0; right: 0; background-color: #2a2a2a; color: #e0e0e0; padding: 16px; text-align: center; font-size: 14px; z-index: 9999; box-shadow: 0 -2px 10px rgba(0,0,0,0.5);">
563
- By continuing, you agree to our
564
- Terms (<span style="color: #8cafff;">{{{{terms_url}}}}</span>) &
565
- Privacy Policy (<span style="color: #8cafff;">{{{{privacy_url}}}}</span>)
566
- <br>
567
- <button id="accept-legal" style="margin-top: 15px; margin-bottom: 15px; background: #01c07d; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;">Accept</button>
568
- <br>
569
- Last Update: {{{{last_update}}}}
570
- </div>
571
-
572
- <script>
573
- const banner = document.getElementById('legal-banner');
574
- const acceptBtn = document.getElementById('accept-legal');
575
- acceptBtn.addEventListener('click', () => {{
576
- banner.remove();
577
- }});
578
524
  </script>
579
525
 
580
526
  </body>
581
527
  </html>
582
528
  """
583
529
  html_path.write_text(html_content)
584
-
585
530
  config_path = project_path / "config.json"
586
531
  await asyncio.to_thread(
587
532
  config_path.write_text,
588
533
  f"""{{
589
- "app_metadata": {{
590
- "name": "{descr}",
591
- "version": "1.0.0",
592
- "author": "{host}"
593
- }},
594
- "data_gateways": [
534
+ "app_metadata": {{
535
+ "name": "{descr}",
536
+ "version": "1.0.0",
537
+ "author": "{host}"
538
+ }},
539
+ "data_gateways": [
540
+ {{
541
+ "node_id": "{node_id}",
542
+ "actions": [
595
543
  {{
596
- "type": "transmitter",
597
- "id": "{txID}",
598
- "info": "Ping Your Node"
544
+ "action": "ping_node",
545
+ "info": "Ping Node"
599
546
  }}
600
- ],
601
- "legals": {{
602
- "terms": "https://url_to_your/terms",
603
- "privacy_policy": "https://url_to_your/privacy_policy",
604
- "last_update" : "DD/MM/YYYY"
547
+ ]
605
548
  }}
549
+ ],
550
+ "legals": {{
551
+ "terms": "https://url_to_your/terms",
552
+ "privacy_policy": "https://url_to_your/privacy_policy"
553
+ }},
554
+ "public_key": "{pem_public_oneline}"
606
555
  }}"""
607
- )
608
-
609
- nodemd_path = project_path / "NODE.md"
610
- await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
611
-
612
- Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
613
-
614
- ***
615
-
616
- ### 💻 Using the CLI
617
-
618
- To ping this Node via the command-line interface, use the following command:
619
-
620
- `neuronum activate --tx {txID} 'ping:node'`
621
-
622
- ***
623
-
624
- ### 🐍 With Python
625
556
 
626
- For programmatic access, use the following Python code snippet. This script utilizes the `neuronum` library to activate the transaction and receive a response.
627
-
628
- ```python
629
- import asyncio
630
- import neuronum
631
-
632
- # Set up Cell connection parameters
633
- cell = neuronum.Cell(
634
- host="host", # Cell host
635
- password="password", # Cell password
636
- network="neuronum.net", # Cell network
637
- synapse="synapse" # Cell synapse
638
557
  )
639
-
640
- async def main():
641
- # Define the transaction ID and data payload
642
- TX = "{txID}"
643
- data = {{"ping": "node"}}
644
-
645
- # Activate the transaction and get the response
646
- tx_response = await cell.activate_tx(TX, data)
647
-
648
- # Print the response from the Node
649
- print(tx_response)
650
-
651
- # Run the main asynchronous function
652
- if __name__ == "__main__":
653
- asyncio.run(main())
654
- ```
655
-
656
- 🤖 Via Cellai (Android App - Currently in Testing)
657
- Download the app from the Google Play Store.
658
- Send the command "Ping Node" to Cellai
659
- """)
660
-
661
- click.echo(f"Neuronum Node '{nodeID}' initialized!")
558
+ click.echo(f"Neuronum Node '{node_id}' initialized!")
662
559
 
663
560
 
664
561
  @click.command()
@@ -695,7 +592,7 @@ def start_node(d):
695
592
  click.echo("Starting Node...")
696
593
 
697
594
  project_path = Path.cwd()
698
- script_files = glob.glob("stream.py") + glob.glob("app.py")
595
+ script_files = glob.glob("app.py")
699
596
  processes = []
700
597
 
701
598
  for script in script_files:
@@ -732,14 +629,12 @@ def start_node(d):
732
629
  def check_node():
733
630
  click.echo("Checking Node status...")
734
631
 
735
- env_data = {}
736
632
  try:
737
- with open(".env", "r") as f:
738
- for line in f:
739
- if "=" in line:
740
- key, value = line.strip().split("=", 1)
741
- env_data[key] = value
742
- nodeID = env_data.get("NODE", "")
633
+ with open('config.json', 'r') as f:
634
+ data = json.load(f)
635
+
636
+ nodeID = data['data_gateways'][0]['node_id']
637
+
743
638
  except FileNotFoundError:
744
639
  click.echo("Error: .env with credentials not found")
745
640
  return
@@ -798,14 +693,11 @@ def restart_node(d):
798
693
 
799
694
  start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
800
695
 
801
- env_data = {}
802
696
  try:
803
- with open(".env", "r") as f:
804
- for line in f:
805
- key, value = line.strip().split("=")
806
- env_data[key] = value
697
+ with open('config.json', 'r') as f:
698
+ data = json.load(f)
807
699
 
808
- nodeID = env_data.get("NODE", "")
700
+ nodeID = data['data_gateways'][0]['node_id']
809
701
 
810
702
  except FileNotFoundError:
811
703
  print("Error: .env with credentials not found")
@@ -842,7 +734,7 @@ def restart_node(d):
842
734
 
843
735
  click.echo(f"Starting Node {nodeID}...")
844
736
  project_path = Path.cwd()
845
- script_files = glob.glob("stream.py") + glob.glob("app.py")
737
+ script_files = glob.glob("app.py")
846
738
  processes = []
847
739
 
848
740
  for script in script_files:
@@ -883,14 +775,11 @@ async def async_stop_node():
883
775
 
884
776
  node_pid_path = Path("status.txt")
885
777
 
886
- env_data = {}
887
778
  try:
888
- with open(".env", "r") as f:
889
- for line in f:
890
- key, value = line.strip().split("=")
891
- env_data[key] = value
779
+ with open('config.json', 'r') as f:
780
+ data = json.load(f)
892
781
 
893
- nodeID = env_data.get("NODE", "")
782
+ nodeID = data['data_gateways'][0]['node_id']
894
783
 
895
784
  except FileNotFoundError:
896
785
  print("Error: .env with credentials not found")
@@ -926,10 +815,12 @@ async def async_stop_node():
926
815
  @click.command()
927
816
  def update_node():
928
817
  click.echo("Update your Node")
818
+ credentials_folder_path = Path.home() / ".neuronum"
819
+ env_path = credentials_folder_path / ".env"
929
820
  env_data = {}
930
821
 
931
822
  try:
932
- with open(".env", "r") as f:
823
+ with open(env_path, "r") as f:
933
824
  for line in f:
934
825
  key, value = line.strip().split("=")
935
826
  env_data[key] = value
@@ -976,20 +867,26 @@ def update_node():
976
867
  asyncio.run(async_update_node(node_type, descr, partners))
977
868
 
978
869
  async def async_update_node(node_type: str, descr: str, partners:str) -> None:
870
+ credentials_folder_path = Path.home() / ".neuronum"
871
+ env_path = credentials_folder_path / ".env"
979
872
  env_data = {}
980
873
 
981
874
  try:
982
- with open(".env", "r") as f:
875
+ with open(env_path, "r") as f:
983
876
  for line in f:
984
877
  key, value = line.strip().split("=")
985
878
  env_data[key] = value
986
879
 
987
- nodeID = env_data.get("NODE", "")
988
880
  host = env_data.get("HOST", "")
989
881
  password = env_data.get("PASSWORD", "")
990
882
  network = env_data.get("NETWORK", "")
991
883
  synapse = env_data.get("SYNAPSE", "")
992
884
 
885
+ with open('config.json', 'r') as f:
886
+ data = json.load(f)
887
+
888
+ nodeID = data['data_gateways'][0]['node_id']
889
+
993
890
  except FileNotFoundError:
994
891
  click.echo("Error: .env with credentials not found")
995
892
  return
@@ -998,17 +895,14 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
998
895
  return
999
896
 
1000
897
  try:
1001
- with open("NODE.md", "r") as f:
1002
- nodemd_file = f.read()
1003
-
1004
898
  with open("config.json", "r") as f:
1005
899
  config_file = f.read()
1006
900
 
1007
901
  except FileNotFoundError:
1008
- click.echo("Error: NODE.md file not found")
902
+ click.echo("Error: Config File not found")
1009
903
  return
1010
904
  except Exception as e:
1011
- click.echo(f"Error reading NODE.md file: {e}")
905
+ click.echo(f"Error reading Config file: {e}")
1012
906
  return
1013
907
 
1014
908
  if node_type == "partners":
@@ -1021,7 +915,6 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
1021
915
  "password": password,
1022
916
  "synapse": synapse,
1023
917
  "node_type": node_type,
1024
- "nodemd_file": nodemd_file,
1025
918
  "config_file": config_file,
1026
919
  "descr": descr,
1027
920
  }
@@ -1032,23 +925,24 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
1032
925
  response.raise_for_status()
1033
926
  data = await response.json()
1034
927
  nodeID = data["nodeID"]
1035
- node_url = data["node_url"]
1036
928
  except aiohttp.ClientError as e:
1037
929
  click.echo(f"Error sending request: {e}")
1038
930
  return
1039
931
 
1040
932
  if node_type == "public":
1041
- click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
933
+ click.echo(f"Neuronum Node '{nodeID}' updated!")
1042
934
  else:
1043
935
  click.echo(f"Neuronum Node '{nodeID}' updated!")
1044
936
 
1045
937
 
1046
938
  def update_node_at_start():
1047
939
  click.echo("Update your Node")
940
+ credentials_folder_path = Path.home() / ".neuronum"
941
+ env_path = credentials_folder_path / ".env"
1048
942
  env_data = {}
1049
943
 
1050
944
  try:
1051
- with open(".env", "r") as f:
945
+ with open(env_path, "r") as f:
1052
946
  for line in f:
1053
947
  key, value = line.strip().split("=")
1054
948
  env_data[key] = value
@@ -1095,20 +989,26 @@ def update_node_at_start():
1095
989
  asyncio.run(async_update_node_at_start(node_type, descr, partners))
1096
990
 
1097
991
  async def async_update_node_at_start(node_type: str, descr: str, partners:str) -> None:
992
+ credentials_folder_path = Path.home() / ".neuronum"
993
+ env_path = credentials_folder_path / ".env"
1098
994
  env_data = {}
1099
995
 
1100
996
  try:
1101
- with open(".env", "r") as f:
997
+ with open(env_path, "r") as f:
1102
998
  for line in f:
1103
999
  key, value = line.strip().split("=")
1104
1000
  env_data[key] = value
1105
1001
 
1106
- nodeID = env_data.get("NODE", "")
1107
1002
  host = env_data.get("HOST", "")
1108
1003
  password = env_data.get("PASSWORD", "")
1109
1004
  network = env_data.get("NETWORK", "")
1110
1005
  synapse = env_data.get("SYNAPSE", "")
1111
1006
 
1007
+ with open('config.json', 'r') as f:
1008
+ data = json.load(f)
1009
+
1010
+ nodeID = data['data_gateways'][0]['node_id']
1011
+
1112
1012
  except FileNotFoundError:
1113
1013
  click.echo("Error: .env with credentials not found")
1114
1014
  return
@@ -1117,17 +1017,14 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
1117
1017
  return
1118
1018
 
1119
1019
  try:
1120
- with open("NODE.md", "r") as f:
1121
- nodemd_file = f.read()
1122
-
1123
1020
  with open("config.json", "r") as f:
1124
1021
  config_file = f.read()
1125
1022
 
1126
1023
  except FileNotFoundError:
1127
- click.echo("Error: NODE.md file not found")
1024
+ click.echo("Error: File not found")
1128
1025
  return
1129
1026
  except Exception as e:
1130
- click.echo(f"Error reading NODE.md file: {e}")
1027
+ click.echo(f"Error reading file: {e}")
1131
1028
  return
1132
1029
 
1133
1030
  if node_type == "partners":
@@ -1140,7 +1037,6 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
1140
1037
  "password": password,
1141
1038
  "synapse": synapse,
1142
1039
  "node_type": node_type,
1143
- "nodemd_file": nodemd_file,
1144
1040
  "config_file": config_file,
1145
1041
  "descr": descr,
1146
1042
  }
@@ -1151,13 +1047,12 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
1151
1047
  response.raise_for_status()
1152
1048
  data = await response.json()
1153
1049
  nodeID = data["nodeID"]
1154
- node_url = data["node_url"]
1155
1050
  except aiohttp.ClientError as e:
1156
1051
  click.echo(f"Error sending request: {e}")
1157
1052
  return
1158
1053
 
1159
1054
  if node_type == "public":
1160
- click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
1055
+ click.echo(f"Neuronum Node '{nodeID}' updated!")
1161
1056
  else:
1162
1057
  click.echo(f"Neuronum Node '{nodeID}' updated!")
1163
1058
 
@@ -1167,20 +1062,26 @@ def delete_node():
1167
1062
  asyncio.run(async_delete_node())
1168
1063
 
1169
1064
  async def async_delete_node():
1065
+ credentials_folder_path = Path.home() / ".neuronum"
1066
+ env_path = credentials_folder_path / ".env"
1170
1067
  env_data = {}
1171
1068
 
1172
1069
  try:
1173
- with open(".env", "r") as f:
1070
+ with open(env_path, "r") as f:
1174
1071
  for line in f:
1175
1072
  key, value = line.strip().split("=")
1176
1073
  env_data[key] = value
1177
1074
 
1178
- nodeID = env_data.get("NODE", "")
1179
1075
  host = env_data.get("HOST", "")
1180
1076
  password = env_data.get("PASSWORD", "")
1181
1077
  network = env_data.get("NETWORK", "")
1182
1078
  synapse = env_data.get("SYNAPSE", "")
1183
1079
 
1080
+ with open('config.json', 'r') as f:
1081
+ data = json.load(f)
1082
+
1083
+ nodeID = data['data_gateways'][0]['node_id']
1084
+
1184
1085
  except FileNotFoundError:
1185
1086
  click.echo("Error: .env with credentials not found")
1186
1087
  return
@@ -1209,130 +1110,6 @@ async def async_delete_node():
1209
1110
  click.echo(f"Neuronum Node '{nodeID}' deleted!")
1210
1111
 
1211
1112
 
1212
- @click.command()
1213
- @click.option('--tx', required=True, help="Transmitter ID")
1214
- @click.argument('kvpairs', nargs=-1)
1215
- def activate(tx, kvpairs):
1216
- try:
1217
- data = dict(pair.split(':', 1) for pair in kvpairs)
1218
- except ValueError:
1219
- click.echo("Invalid input. Use key:value pairs.")
1220
- return
1221
-
1222
- asyncio.run(async_activate(tx, data))
1223
-
1224
- async def async_activate(tx, data):
1225
- credentials_folder_path = Path.home() / ".neuronum"
1226
- env_path = credentials_folder_path / ".env"
1227
- env_data = {}
1228
-
1229
- try:
1230
- with open(env_path, "r") as f:
1231
- for line in f:
1232
- key, value = line.strip().split("=")
1233
- env_data[key] = value
1234
- except FileNotFoundError:
1235
- click.echo("No cell connected. Try: neuronum connect-cell")
1236
- return
1237
- except Exception as e:
1238
- click.echo(f"Error reading .env: {e}")
1239
- return
1240
-
1241
- cell = neuronum.Cell(
1242
- host=env_data.get("HOST", ""),
1243
- password=env_data.get("PASSWORD", ""),
1244
- network=env_data.get("NETWORK", ""),
1245
- synapse=env_data.get("SYNAPSE", "")
1246
- )
1247
-
1248
- tx_response = await cell.activate_tx(tx, data)
1249
- click.echo(tx_response)
1250
-
1251
-
1252
- @click.command()
1253
- @click.option('--ctx', required=True, help="Circuit ID")
1254
- @click.argument('label', nargs=-1)
1255
- def load(ctx, label):
1256
- if len(label) > 1 and all(Path(x).exists() for x in label):
1257
- label = "*"
1258
- else:
1259
- label = " ".join(label)
1260
-
1261
- asyncio.run(async_load(ctx, label))
1262
-
1263
-
1264
- async def async_load(ctx, label):
1265
- credentials_folder_path = Path.home() / ".neuronum"
1266
- env_path = credentials_folder_path / ".env"
1267
- env_data = {}
1268
-
1269
- try:
1270
- with open(env_path, "r") as f:
1271
- for line in f:
1272
- key, value = line.strip().split("=")
1273
- env_data[key] = value
1274
- except FileNotFoundError:
1275
- click.echo("No cell connected. Try: neuronum connect-cell")
1276
- return
1277
- except Exception as e:
1278
- click.echo(f"Error reading .env: {e}")
1279
- return
1280
-
1281
- cell = neuronum.Cell(
1282
- host=env_data.get("HOST", ""),
1283
- password=env_data.get("PASSWORD", ""),
1284
- network=env_data.get("NETWORK", ""),
1285
- synapse=env_data.get("SYNAPSE", "")
1286
- )
1287
-
1288
- data = await cell.load(label, ctx)
1289
- click.echo(data)
1290
-
1291
-
1292
- @click.command()
1293
- @click.option('--stx', default=None, help="Stream ID (optional)")
1294
- def sync(stx):
1295
- asyncio.run(async_sync(stx))
1296
-
1297
-
1298
- async def async_sync(stx):
1299
- credentials_folder_path = Path.home() / ".neuronum"
1300
- env_path = credentials_folder_path / ".env"
1301
- env_data = {}
1302
-
1303
- try:
1304
- with open(env_path, "r") as f:
1305
- for line in f:
1306
- key, value = line.strip().split("=")
1307
- env_data[key] = value
1308
- except FileNotFoundError:
1309
- click.echo("No cell connected. Try: neuronum connect-cell")
1310
- return
1311
- except Exception as e:
1312
- click.echo(f"Error reading .env: {e}")
1313
- return
1314
-
1315
- cell = neuronum.Cell(
1316
- host=env_data.get("HOST", ""),
1317
- password=env_data.get("PASSWORD", ""),
1318
- network=env_data.get("NETWORK", ""),
1319
- synapse=env_data.get("SYNAPSE", "")
1320
- )
1321
-
1322
- if stx:
1323
- print(f"Listening to Stream '{stx}'! Close connection with CTRL+C")
1324
- else:
1325
- print(f"Listening to '{cell.host}' private Stream! Close connection with CTRL+C")
1326
- async for operation in cell.sync() if stx is None else cell.sync(stx):
1327
- label = operation.get("label")
1328
- data = operation.get("data")
1329
- ts = operation.get("time")
1330
- stxID = operation.get("stxID")
1331
- operator = operation.get("operator")
1332
- txID = operation.get("txID")
1333
- print(label, data, ts, operator, txID, stxID)
1334
-
1335
-
1336
1113
  cli.add_command(create_cell)
1337
1114
  cli.add_command(connect_cell)
1338
1115
  cli.add_command(view_cell)
@@ -1345,9 +1122,6 @@ cli.add_command(restart_node)
1345
1122
  cli.add_command(stop_node)
1346
1123
  cli.add_command(check_node)
1347
1124
  cli.add_command(delete_node)
1348
- cli.add_command(activate)
1349
- cli.add_command(load)
1350
- cli.add_command(sync)
1351
1125
 
1352
1126
 
1353
1127
  if __name__ == "__main__":