neuronum 1.5.1__py3-none-any.whl → 1.6.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/__init__.py +0 -0
- cli/main.py +341 -0
- neuronum/neuronum.py +148 -73
- {neuronum-1.5.1.dist-info → neuronum-1.6.0.dist-info}/METADATA +99 -34
- neuronum-1.6.0.dist-info/RECORD +10 -0
- neuronum-1.6.0.dist-info/entry_points.txt +2 -0
- {neuronum-1.5.1.dist-info → neuronum-1.6.0.dist-info}/top_level.txt +1 -0
- neuronum-1.5.1.dist-info/RECORD +0 -7
- {neuronum-1.5.1.dist-info → neuronum-1.6.0.dist-info}/LICENSE +0 -0
- {neuronum-1.5.1.dist-info → neuronum-1.6.0.dist-info}/WHEEL +0 -0
cli/__init__.py
ADDED
|
File without changes
|
cli/main.py
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import questionary
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import requests
|
|
5
|
+
import subprocess
|
|
6
|
+
import os
|
|
7
|
+
import neuronum
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
@click.group()
|
|
11
|
+
def cli():
|
|
12
|
+
"""Neuronum CLI Tool"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
def init_node():
|
|
17
|
+
click.echo("Initialize Node")
|
|
18
|
+
|
|
19
|
+
node_type = questionary.select(
|
|
20
|
+
"Choose Node type:",
|
|
21
|
+
choices=["public", "private"]
|
|
22
|
+
).ask()
|
|
23
|
+
|
|
24
|
+
descr = click.prompt("Node description (max. 25 characters)")
|
|
25
|
+
host = click.prompt("Enter your cell host")
|
|
26
|
+
password = click.prompt("Enter your password", hide_input=True)
|
|
27
|
+
network = click.prompt("Enter your network")
|
|
28
|
+
synapse = click.prompt("Enter your synapse", hide_input=True)
|
|
29
|
+
|
|
30
|
+
cell = neuronum.Cell(
|
|
31
|
+
host=host,
|
|
32
|
+
password=password,
|
|
33
|
+
network=network,
|
|
34
|
+
synapse=synapse
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
tx = cell.list_tx()
|
|
38
|
+
ctx = cell.list_ctx()
|
|
39
|
+
stx = cell.list_stx()
|
|
40
|
+
contracts = cell.list_contracts()
|
|
41
|
+
|
|
42
|
+
url = f"https://{network}/api/init_node/{node_type}"
|
|
43
|
+
|
|
44
|
+
node = {"descr": descr, "host": host, "password": password, "synapse": synapse}
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
response = requests.post(url, json=node)
|
|
48
|
+
response.raise_for_status()
|
|
49
|
+
nodeID = response.json()["nodeID"]
|
|
50
|
+
except requests.exceptions.RequestException as e:
|
|
51
|
+
click.echo(f"Error sending request: {e}")
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
node_filename = "node"
|
|
55
|
+
project_path = Path(node_filename)
|
|
56
|
+
project_path.mkdir(exist_ok=True)
|
|
57
|
+
|
|
58
|
+
env_path = project_path / ".env"
|
|
59
|
+
env_path.write_text(f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
60
|
+
|
|
61
|
+
tx_path = project_path / "transmitters.json"
|
|
62
|
+
tx_path.write_text(json.dumps(tx, indent=4))
|
|
63
|
+
|
|
64
|
+
ctx_path = project_path / "circuits.json"
|
|
65
|
+
ctx_path.write_text(json.dumps(ctx, indent=4))
|
|
66
|
+
|
|
67
|
+
stx_path = project_path / "streams.json"
|
|
68
|
+
stx_path.write_text(json.dumps(stx, indent=4))
|
|
69
|
+
|
|
70
|
+
contracts_path = project_path / "contracts.json"
|
|
71
|
+
contracts_path.write_text(json.dumps(contracts, indent=4))
|
|
72
|
+
|
|
73
|
+
nodemd_path = project_path / "NODE.md"
|
|
74
|
+
nodemd_path.write_text("""\
|
|
75
|
+
#some markdown
|
|
76
|
+
""")
|
|
77
|
+
|
|
78
|
+
main_path = project_path / "main.py"
|
|
79
|
+
main_path.write_text("""\
|
|
80
|
+
import neuronum
|
|
81
|
+
import os
|
|
82
|
+
from dotenv import load_dotenv
|
|
83
|
+
|
|
84
|
+
load_dotenv()
|
|
85
|
+
host = os.getenv("HOST")
|
|
86
|
+
password = os.getenv("PASSWORD")
|
|
87
|
+
network = os.getenv("NETWORK")
|
|
88
|
+
synapse = os.getenv("SYNAPSE")
|
|
89
|
+
|
|
90
|
+
#set cell connection
|
|
91
|
+
cell = neuronum.Cell(
|
|
92
|
+
host=host,
|
|
93
|
+
password=password,
|
|
94
|
+
network=network,
|
|
95
|
+
synapse=synapse
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
STX = "n9gW3LxQcecI::stx"
|
|
99
|
+
stream = cell.sync(STX)
|
|
100
|
+
for operation in stream:
|
|
101
|
+
label = operation.get("label")
|
|
102
|
+
value = operation.get("data").get("message")
|
|
103
|
+
ts = operation.get("time")
|
|
104
|
+
stxID = operation.get("stxID")
|
|
105
|
+
operator = operation.get("operator")
|
|
106
|
+
print(label, value, ts, stxID, operator)
|
|
107
|
+
""")
|
|
108
|
+
|
|
109
|
+
click.echo(f"Neuronum Node '{nodeID}' initialized!")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@click.command()
|
|
113
|
+
def start_node():
|
|
114
|
+
click.echo("Starting Node...")
|
|
115
|
+
|
|
116
|
+
project_path = Path.cwd()
|
|
117
|
+
main_file = project_path / "main.py"
|
|
118
|
+
|
|
119
|
+
if not main_file.exists():
|
|
120
|
+
click.echo("Error: main.py not found. Make sure the node is set up.")
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
process = subprocess.Popen(["python", str(main_file)], start_new_session=True)
|
|
124
|
+
|
|
125
|
+
with open("node_pid.txt", "w") as f:
|
|
126
|
+
f.write(str(process.pid))
|
|
127
|
+
|
|
128
|
+
click.echo("Neuronum Node started successfully!")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@click.command()
|
|
132
|
+
def stop_node():
|
|
133
|
+
"""Stops the Neuronum node"""
|
|
134
|
+
click.echo("Stopping Neuronum Node...")
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
with open("node_pid.txt", "r") as f:
|
|
138
|
+
pid = int(f.read().strip())
|
|
139
|
+
os.kill(pid, 9)
|
|
140
|
+
os.remove("node_pid.txt")
|
|
141
|
+
click.echo("Neuronum Node stopped successfully!")
|
|
142
|
+
except FileNotFoundError:
|
|
143
|
+
click.echo("Error: No active node process found.")
|
|
144
|
+
except Exception as e:
|
|
145
|
+
click.echo(f"Error stopping node: {e}")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@click.command()
|
|
149
|
+
def register_node():
|
|
150
|
+
click.echo("Register Node")
|
|
151
|
+
|
|
152
|
+
env_data = {}
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
with open(".env", "r") as f:
|
|
156
|
+
for line in f:
|
|
157
|
+
key, value = line.strip().split("=")
|
|
158
|
+
env_data[key] = value
|
|
159
|
+
|
|
160
|
+
nodeID = env_data.get("NODE", "")
|
|
161
|
+
host = env_data.get("HOST", "")
|
|
162
|
+
password = env_data.get("PASSWORD", "")
|
|
163
|
+
network = env_data.get("NETWORK", "")
|
|
164
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
165
|
+
|
|
166
|
+
except FileNotFoundError:
|
|
167
|
+
print("Error: .env with credentials not found")
|
|
168
|
+
return
|
|
169
|
+
except Exception as e:
|
|
170
|
+
print(f"Error reading .env file: {e}")
|
|
171
|
+
return
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
with open("NODE.md", "r") as f:
|
|
175
|
+
nodemd_file = f.read()
|
|
176
|
+
|
|
177
|
+
except FileNotFoundError:
|
|
178
|
+
print("Error: NODE.md file not found")
|
|
179
|
+
return
|
|
180
|
+
except Exception as e:
|
|
181
|
+
print(f"Error reading NODE.md file: {e}")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
url = f"https://{network}/api/register_node"
|
|
185
|
+
|
|
186
|
+
node = {
|
|
187
|
+
"nodeID": nodeID,
|
|
188
|
+
"host": host,
|
|
189
|
+
"password": password,
|
|
190
|
+
"synapse": synapse,
|
|
191
|
+
"nodemd_file": nodemd_file
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
response = requests.post(url, json=node)
|
|
196
|
+
response.raise_for_status()
|
|
197
|
+
nodeID = response.json()["nodeID"]
|
|
198
|
+
node_url = response.json()["node_url"]
|
|
199
|
+
except requests.exceptions.RequestException as e:
|
|
200
|
+
click.echo(f"Error sending request: {e}")
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
click.echo(f"Neuronum Node '{nodeID}' registered! Visit: {node_url}")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@click.command()
|
|
207
|
+
def update_node():
|
|
208
|
+
click.echo("Update Node")
|
|
209
|
+
|
|
210
|
+
env_data = {}
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
with open(".env", "r") as f:
|
|
214
|
+
for line in f:
|
|
215
|
+
key, value = line.strip().split("=")
|
|
216
|
+
env_data[key] = value
|
|
217
|
+
|
|
218
|
+
nodeID = env_data.get("NODE", "")
|
|
219
|
+
host = env_data.get("HOST", "")
|
|
220
|
+
password = env_data.get("PASSWORD", "")
|
|
221
|
+
network = env_data.get("NETWORK", "")
|
|
222
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
223
|
+
|
|
224
|
+
except FileNotFoundError:
|
|
225
|
+
print("Error: .env with credentials not found")
|
|
226
|
+
return
|
|
227
|
+
except Exception as e:
|
|
228
|
+
print(f"Error reading .env file: {e}")
|
|
229
|
+
return
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
with open("NODE.md", "r") as f:
|
|
233
|
+
nodemd_file = f.read()
|
|
234
|
+
|
|
235
|
+
except FileNotFoundError:
|
|
236
|
+
print("Error: NODE.md file not found")
|
|
237
|
+
return
|
|
238
|
+
except Exception as e:
|
|
239
|
+
print(f"Error reading NODE.md file: {e}")
|
|
240
|
+
return
|
|
241
|
+
|
|
242
|
+
url = f"https://{network}/api/update_node"
|
|
243
|
+
|
|
244
|
+
node = {
|
|
245
|
+
"nodeID": nodeID,
|
|
246
|
+
"host": host,
|
|
247
|
+
"password": password,
|
|
248
|
+
"synapse": synapse,
|
|
249
|
+
"nodemd_file": nodemd_file
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
response = requests.post(url, json=node)
|
|
254
|
+
response.raise_for_status()
|
|
255
|
+
nodeID = response.json()["nodeID"]
|
|
256
|
+
node_url = response.json()["node_url"]
|
|
257
|
+
except requests.exceptions.RequestException as e:
|
|
258
|
+
click.echo(f"Error sending request: {e}")
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
cell = neuronum.Cell(
|
|
263
|
+
host=host,
|
|
264
|
+
password=password,
|
|
265
|
+
network=network,
|
|
266
|
+
synapse=synapse
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
tx = cell.list_tx()
|
|
270
|
+
ctx = cell.list_ctx()
|
|
271
|
+
stx = cell.list_stx()
|
|
272
|
+
contracts = cell.list_contracts()
|
|
273
|
+
|
|
274
|
+
tx_path = Path("transmitters.json")
|
|
275
|
+
ctx_path = Path("circuits.json")
|
|
276
|
+
stx_path = Path("streams.json")
|
|
277
|
+
contracts_path = Path("contracts.json")
|
|
278
|
+
|
|
279
|
+
tx_path.write_text(json.dumps(tx, indent=4))
|
|
280
|
+
ctx_path.write_text(json.dumps(ctx, indent=4))
|
|
281
|
+
stx_path.write_text(json.dumps(stx, indent=4))
|
|
282
|
+
contracts_path.write_text(json.dumps(contracts, indent=4))
|
|
283
|
+
|
|
284
|
+
click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@click.command()
|
|
288
|
+
def delete_node():
|
|
289
|
+
click.echo("Delete Node")
|
|
290
|
+
|
|
291
|
+
env_data = {}
|
|
292
|
+
|
|
293
|
+
try:
|
|
294
|
+
with open(".env", "r") as f:
|
|
295
|
+
for line in f:
|
|
296
|
+
key, value = line.strip().split("=")
|
|
297
|
+
env_data[key] = value
|
|
298
|
+
|
|
299
|
+
nodeID = env_data.get("NODE", "")
|
|
300
|
+
host = env_data.get("HOST", "")
|
|
301
|
+
password = env_data.get("PASSWORD", "")
|
|
302
|
+
network = env_data.get("NETWORK", "")
|
|
303
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
304
|
+
|
|
305
|
+
except FileNotFoundError:
|
|
306
|
+
print("Error: .env with credentials not found")
|
|
307
|
+
return
|
|
308
|
+
except Exception as e:
|
|
309
|
+
print(f"Error reading .env file: {e}")
|
|
310
|
+
return
|
|
311
|
+
|
|
312
|
+
url = f"https://{network}/api/delete_node"
|
|
313
|
+
|
|
314
|
+
node = {
|
|
315
|
+
"nodeID": nodeID,
|
|
316
|
+
"host": host,
|
|
317
|
+
"password": password,
|
|
318
|
+
"synapse": synapse
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
try:
|
|
322
|
+
response = requests.post(url, json=node)
|
|
323
|
+
response.raise_for_status()
|
|
324
|
+
nodeID = response.json()["nodeID"]
|
|
325
|
+
except requests.exceptions.RequestException as e:
|
|
326
|
+
click.echo(f"Error sending request: {e}")
|
|
327
|
+
return
|
|
328
|
+
|
|
329
|
+
click.echo(f"Neuronum Node '{nodeID}' deleted!")
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
cli.add_command(init_node)
|
|
333
|
+
cli.add_command(start_node)
|
|
334
|
+
cli.add_command(stop_node)
|
|
335
|
+
cli.add_command(register_node)
|
|
336
|
+
cli.add_command(update_node)
|
|
337
|
+
cli.add_command(delete_node)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
if __name__ == "__main__":
|
|
341
|
+
cli()
|
neuronum/neuronum.py
CHANGED
|
@@ -206,108 +206,51 @@ class Cell:
|
|
|
206
206
|
print(f"Unexpected error: {e}")
|
|
207
207
|
|
|
208
208
|
|
|
209
|
-
def
|
|
210
|
-
if mode == "public":
|
|
211
|
-
url = f"https://{self.network}/api/register_node/public"
|
|
212
|
-
elif mode == "private":
|
|
213
|
-
url = f"https://{self.network}/api/register_node/private"
|
|
214
|
-
else:
|
|
215
|
-
return {"error": "Invalid mode", "message": "Mode has to be 'public' or 'private'"}
|
|
216
|
-
|
|
217
|
-
node_data = {
|
|
218
|
-
"descr": descr,
|
|
219
|
-
"mode": mode,
|
|
220
|
-
"stream": stx,
|
|
221
|
-
"cell": self.to_dict()
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
try:
|
|
225
|
-
response = requests.post(
|
|
226
|
-
url,
|
|
227
|
-
json=node_data,
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
response.raise_for_status()
|
|
231
|
-
|
|
232
|
-
return response.json()["nodeID"]
|
|
233
|
-
|
|
234
|
-
except requests.exceptions.RequestException as e:
|
|
235
|
-
print(f"Error sending request: {e}")
|
|
236
|
-
except Exception as e:
|
|
237
|
-
print(f"Unexpected error: {e}")
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
def delete_node(self, nodeID: str):
|
|
241
|
-
url = f"https://{self.network}/api/delete_node"
|
|
242
|
-
|
|
243
|
-
delete_node = {
|
|
244
|
-
"nodeID": nodeID,
|
|
245
|
-
"cell": self.to_dict()
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
try:
|
|
249
|
-
response = requests.post(
|
|
250
|
-
url,
|
|
251
|
-
json=delete_node,
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
response.raise_for_status()
|
|
255
|
-
print(response.json())
|
|
256
|
-
|
|
257
|
-
except requests.exceptions.RequestException as e:
|
|
258
|
-
print(f"Error sending request: {e}")
|
|
259
|
-
except Exception as e:
|
|
260
|
-
print(f"Unexpected error: {e}")
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
def list_tx(self, cellID: str):
|
|
209
|
+
def list_tx(self):
|
|
264
210
|
full_url = f"https://{self.network}/api/list_tx"
|
|
265
211
|
|
|
266
212
|
list_tx = {
|
|
267
|
-
"cell": self.to_dict()
|
|
268
|
-
"cellID": cellID
|
|
213
|
+
"cell": self.to_dict()
|
|
269
214
|
}
|
|
270
215
|
|
|
271
216
|
try:
|
|
272
217
|
response = requests.post(full_url, json=list_tx)
|
|
273
218
|
response.raise_for_status()
|
|
274
|
-
return response.json()
|
|
219
|
+
return response.json()["Transmitters"]
|
|
275
220
|
except requests.exceptions.RequestException as e:
|
|
276
221
|
print(f"Error sending request: {e}")
|
|
277
222
|
except Exception as e:
|
|
278
223
|
print(f"Unexpected error: {e}")
|
|
279
224
|
|
|
280
225
|
|
|
281
|
-
def list_ctx(self
|
|
226
|
+
def list_ctx(self):
|
|
282
227
|
full_url = f"https://{self.network}/api/list_ctx"
|
|
283
228
|
|
|
284
229
|
list_ctx = {
|
|
285
|
-
"cell": self.to_dict()
|
|
286
|
-
"cellID": cellID
|
|
230
|
+
"cell": self.to_dict()
|
|
287
231
|
}
|
|
288
232
|
|
|
289
233
|
try:
|
|
290
234
|
response = requests.post(full_url, json=list_ctx)
|
|
291
235
|
response.raise_for_status()
|
|
292
|
-
return response.json()
|
|
236
|
+
return response.json()["Circuits"]
|
|
293
237
|
except requests.exceptions.RequestException as e:
|
|
294
238
|
print(f"Error sending request: {e}")
|
|
295
239
|
except Exception as e:
|
|
296
240
|
print(f"Unexpected error: {e}")
|
|
297
241
|
|
|
298
242
|
|
|
299
|
-
def list_stx(self
|
|
243
|
+
def list_stx(self):
|
|
300
244
|
full_url = f"https://{self.network}/api/list_stx"
|
|
301
245
|
|
|
302
246
|
list_stx = {
|
|
303
|
-
"cell": self.to_dict()
|
|
304
|
-
"cellID": cellID
|
|
247
|
+
"cell": self.to_dict()
|
|
305
248
|
}
|
|
306
249
|
|
|
307
250
|
try:
|
|
308
251
|
response = requests.post(full_url, json=list_stx)
|
|
309
252
|
response.raise_for_status()
|
|
310
|
-
return response.json()
|
|
253
|
+
return response.json()["Streams"]
|
|
311
254
|
except requests.exceptions.RequestException as e:
|
|
312
255
|
print(f"Error sending request: {e}")
|
|
313
256
|
except Exception as e:
|
|
@@ -459,14 +402,13 @@ class Cell:
|
|
|
459
402
|
try:
|
|
460
403
|
ws = create_connection(f"wss://{self.network}/sync/{stx}")
|
|
461
404
|
ws.send(json.dumps(auth))
|
|
462
|
-
print("
|
|
405
|
+
print("Listening to Stream...")
|
|
463
406
|
|
|
464
407
|
try:
|
|
465
408
|
while True:
|
|
466
409
|
try:
|
|
467
410
|
raw_operation = ws.recv()
|
|
468
411
|
operation = json.loads(raw_operation)
|
|
469
|
-
print("Listening to Stream...")
|
|
470
412
|
yield operation
|
|
471
413
|
|
|
472
414
|
except socket.timeout:
|
|
@@ -474,17 +416,150 @@ class Cell:
|
|
|
474
416
|
continue
|
|
475
417
|
|
|
476
418
|
except KeyboardInterrupt:
|
|
477
|
-
print("Stream-Synchronization ended!")
|
|
478
|
-
except Exception as e:
|
|
479
|
-
print(f"Error: {e}")
|
|
480
|
-
finally:
|
|
481
419
|
ws.close()
|
|
482
420
|
print("Connection closed.")
|
|
483
|
-
|
|
421
|
+
except Exception as e:
|
|
422
|
+
print(f"Error: {e}")
|
|
423
|
+
|
|
424
|
+
|
|
484
425
|
except KeyboardInterrupt:
|
|
485
426
|
print("Stream-Synchronization ended!")
|
|
486
427
|
ws.close()
|
|
487
428
|
print("Connection closed. Goodbye!")
|
|
488
429
|
|
|
489
430
|
|
|
431
|
+
def sign_contract(self, contractID: str):
|
|
432
|
+
full_url = f"https://{self.network}/api/sign_contract"
|
|
433
|
+
|
|
434
|
+
sign_contract = {
|
|
435
|
+
"contractID": contractID,
|
|
436
|
+
"cell": self.to_dict()
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
try:
|
|
440
|
+
response = requests.post(full_url, json=sign_contract)
|
|
441
|
+
response.raise_for_status()
|
|
442
|
+
return response.json()["token"]
|
|
443
|
+
except requests.exceptions.RequestException as e:
|
|
444
|
+
print(f"Error sending request: {e}")
|
|
445
|
+
except Exception as e:
|
|
446
|
+
print(f"Unexpected error: {e}")
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def validate_token(self, token: str, cp: str, contractID: str):
|
|
450
|
+
full_url = f"https://{self.network}/api/validate_token"
|
|
451
|
+
|
|
452
|
+
validate = {
|
|
453
|
+
"token": token,
|
|
454
|
+
"cp": cp,
|
|
455
|
+
"contractID": contractID,
|
|
456
|
+
"cell": self.to_dict()
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
try:
|
|
460
|
+
response = requests.post(full_url, json=validate)
|
|
461
|
+
response.raise_for_status()
|
|
462
|
+
return response.json()["validity"]
|
|
463
|
+
except requests.exceptions.RequestException as e:
|
|
464
|
+
print(f"Error sending request: {e}")
|
|
465
|
+
except Exception as e:
|
|
466
|
+
print(f"Unexpected error: {e}")
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def request_token(self, cp: str, contractID: str):
|
|
470
|
+
full_url = f"https://{self.network}/api/request_token"
|
|
471
|
+
|
|
472
|
+
request_token = {
|
|
473
|
+
"cp": cp,
|
|
474
|
+
"contractID": contractID,
|
|
475
|
+
"cell": self.to_dict()
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
try:
|
|
479
|
+
response = requests.post(full_url, json=request_token)
|
|
480
|
+
response.raise_for_status()
|
|
481
|
+
print(response.json())
|
|
482
|
+
except requests.exceptions.RequestException as e:
|
|
483
|
+
print(f"Error sending request: {e}")
|
|
484
|
+
except Exception as e:
|
|
485
|
+
print(f"Unexpected error: {e}")
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
def present_token(self, token: str, cp: str, contractID: str):
|
|
489
|
+
full_url = f"https://{self.network}/api/present_token"
|
|
490
|
+
|
|
491
|
+
present_token = {
|
|
492
|
+
"token": token,
|
|
493
|
+
"cp": cp,
|
|
494
|
+
"contractID": contractID,
|
|
495
|
+
"cell": self.to_dict()
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
try:
|
|
499
|
+
response = requests.post(full_url, json=present_token)
|
|
500
|
+
response.raise_for_status()
|
|
501
|
+
print(response.json())
|
|
502
|
+
except requests.exceptions.RequestException as e:
|
|
503
|
+
print(f"Error sending request: {e}")
|
|
504
|
+
except Exception as e:
|
|
505
|
+
print(f"Unexpected error: {e}")
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def create_contract(self, descr: str, details: dict, partners: list):
|
|
509
|
+
full_url = f"https://{self.network}/api/create_contract"
|
|
510
|
+
|
|
511
|
+
create_contract = {
|
|
512
|
+
"cell": self.to_dict(),
|
|
513
|
+
"descr": descr,
|
|
514
|
+
"details": details,
|
|
515
|
+
"partners": partners
|
|
516
|
+
}
|
|
517
|
+
try:
|
|
518
|
+
response = requests.post(full_url, json=create_contract)
|
|
519
|
+
response.raise_for_status()
|
|
520
|
+
return response.json()["contractID"]
|
|
521
|
+
except requests.exceptions.RequestException as e:
|
|
522
|
+
print(f"Error sending request: {e}")
|
|
523
|
+
except Exception as e:
|
|
524
|
+
print(f"Unexpected error: {e}")
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def delete_contract(self, contractID: str):
|
|
528
|
+
full_url = f"https://{self.network}/api/delete_contract"
|
|
529
|
+
|
|
530
|
+
request = {
|
|
531
|
+
"cell": self.to_dict(),
|
|
532
|
+
"contractID": contractID
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
try:
|
|
536
|
+
response = requests.post(full_url, json=request)
|
|
537
|
+
response.raise_for_status()
|
|
538
|
+
print(f"Response from Neuronum: {response.json()}")
|
|
539
|
+
except requests.exceptions.RequestException as e:
|
|
540
|
+
print(f"Error sending request: {e}")
|
|
541
|
+
except Exception as e:
|
|
542
|
+
print(f"Unexpected error: {e}")
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def list_contracts(self):
|
|
546
|
+
full_url = f"https://{self.network}/api/list_contracts"
|
|
547
|
+
|
|
548
|
+
list_contracts = {
|
|
549
|
+
"cell": self.to_dict()
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
try:
|
|
553
|
+
response = requests.post(full_url, json=list_contracts)
|
|
554
|
+
response.raise_for_status()
|
|
555
|
+
return response.json()["Contracts"]
|
|
556
|
+
except requests.exceptions.RequestException as e:
|
|
557
|
+
print(f"Error sending request: {e}")
|
|
558
|
+
except Exception as e:
|
|
559
|
+
print(f"Unexpected error: {e}")
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
|
|
490
565
|
__all__ = ['Cell']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Interact with the Neuronum Network to build & automate interconnected networks of soft- and hardware components
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -14,33 +14,36 @@ Description-Content-Type: text/markdown
|
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: requests
|
|
16
16
|
Requires-Dist: websocket-client
|
|
17
|
+
Requires-Dist: click
|
|
18
|
+
Requires-Dist: questionary
|
|
19
|
+
Requires-Dist: python-dotenv
|
|
17
20
|
|
|
18
21
|

|
|
19
22
|
|
|
20
|
-
[](https://neuronum.net)
|
|
21
|
-
[](https://github.com/neuronumcybernetics/neuronum)
|
|
22
|
-
[](https://www.youtube.com/@neuronumnet)
|
|
23
|
+
[](https://neuronum.net) [](https://github.com/neuronumcybernetics/neuronum)
|
|
23
24
|
|
|
24
25
|
`Neuronum` is a cybernetic framework enabling businesses to build & automate interconnected networks of soft- and hardware components
|
|
25
26
|
|
|
26
27
|
## Features
|
|
27
28
|
- **Cell**: Identity to connect and interact with the Neuronum Network
|
|
29
|
+
- **Nodes/Node-CLI**: Setup and manage Neuronum Nodes from the command line.
|
|
28
30
|
- **Transmitters (TX)**: Automate economic data transfer
|
|
29
31
|
- **Circuits (CTX)**: Store data in Key-Value-Label databases
|
|
30
32
|
- **Streams (STX)**: Stream, synchronize and control data in real time
|
|
31
|
-
- **
|
|
33
|
+
- **Contracts/Tokens**: Automate contract-based authorization between Nodes and Cells
|
|
32
34
|
|
|
33
|
-
To interact with the Network you will need to create a Neuronum Cell.
|
|
34
|
-
Create your Cell: [Create Cell](https://neuronum.net/createcell)
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Start with installing the Neuronum library using pip:
|
|
36
|
+
### Installation
|
|
37
|
+
Install the Neuronum library using pip:
|
|
39
38
|
```python
|
|
40
39
|
pip install neuronum
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
### Cell
|
|
43
|
+
To interact with the Network you will need to create a Neuronum Cell.
|
|
44
|
+
Create your Cell: [Create Cell](https://neuronum.net/createcell)
|
|
45
|
+
|
|
46
|
+
Set and test Cell connection:
|
|
44
47
|
```python
|
|
45
48
|
import neuronum
|
|
46
49
|
|
|
@@ -53,6 +56,39 @@ synapse="your_synapse" # cell synapse
|
|
|
53
56
|
cell.connect() # connect to network
|
|
54
57
|
```
|
|
55
58
|
|
|
59
|
+
### Nodes/Node-CLI
|
|
60
|
+
Neuronum Nodes are computing hardware powered by the Neuronum library, enabling seamless communication between Nodes and Cells.
|
|
61
|
+
|
|
62
|
+
Initialize your Node:
|
|
63
|
+
```bash
|
|
64
|
+
>>> neuronum init-node
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Start your Node:
|
|
68
|
+
```bash
|
|
69
|
+
>>> neuronum start-node
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Stop your Node:
|
|
73
|
+
```bash
|
|
74
|
+
>>> neuronum stop-node
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Register your Node on the Neuronum Network:
|
|
78
|
+
```bash
|
|
79
|
+
>>> neuronum register-node
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Update your Node:
|
|
83
|
+
```bash
|
|
84
|
+
>>> neuronum update-node
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Delete your Node:
|
|
88
|
+
```bash
|
|
89
|
+
>>> neuronum delete-node
|
|
90
|
+
```
|
|
91
|
+
|
|
56
92
|
### Transmitters (TX)
|
|
57
93
|
Transmitters (TX) are used to create predefined templates to receive and send data in a standardized format.
|
|
58
94
|
|
|
@@ -87,10 +123,9 @@ TX = "id::tx" # select Trans
|
|
|
87
123
|
cell.delete_tx(TX) # delete TX
|
|
88
124
|
```
|
|
89
125
|
|
|
90
|
-
List Transmitter (TX)
|
|
91
|
-
```python
|
|
92
|
-
|
|
93
|
-
txList = cell.list_tx(cellID) # list Transmitters (TX)
|
|
126
|
+
List Transmitter (TX) your Cell can activate:
|
|
127
|
+
```python
|
|
128
|
+
txList = cell.list_tx() # list Transmitters (TX)
|
|
94
129
|
```
|
|
95
130
|
|
|
96
131
|
### Circuits (CTX)
|
|
@@ -177,10 +212,9 @@ CTX = "id::ctx" # select Circu
|
|
|
177
212
|
cell.delete_ctx(CTX) # delete CTX
|
|
178
213
|
```
|
|
179
214
|
|
|
180
|
-
List Circuits (CTX)
|
|
181
|
-
```python
|
|
182
|
-
|
|
183
|
-
ctxList = cell.list_ctx(cellID) # list Circuits (CTX)
|
|
215
|
+
List Circuits (CTX) your Cell can interact with:
|
|
216
|
+
```python
|
|
217
|
+
ctxList = cell.list_ctx() # list Circuits (CTX)
|
|
184
218
|
```
|
|
185
219
|
|
|
186
220
|
### Streams (STX)
|
|
@@ -243,25 +277,56 @@ for operation in stream: # load stream
|
|
|
243
277
|
operator = operation.get("operator")
|
|
244
278
|
```
|
|
245
279
|
|
|
246
|
-
List Streams (STX)
|
|
247
|
-
```python
|
|
248
|
-
|
|
249
|
-
stxList = cell.list_stx(cellID) # list Streams (STX)
|
|
280
|
+
List Streams (STX) your Cell can interact with:
|
|
281
|
+
```python
|
|
282
|
+
stxList = cell.list_stx() # list Streams (STX)
|
|
250
283
|
```
|
|
251
284
|
|
|
252
|
-
###
|
|
253
|
-
|
|
285
|
+
### Contracts/Tokens
|
|
286
|
+
Contracts define rules for authorization, allowing users to sign and generate unique tokens for secure access
|
|
254
287
|
|
|
255
|
-
|
|
288
|
+
Create a Contract:
|
|
256
289
|
```python
|
|
257
|
-
descr = "
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
290
|
+
descr = "Test Contract" # short description (max 25 characters)
|
|
291
|
+
details = { # define token details
|
|
292
|
+
"price_in_eur": 10, # token price in EUR
|
|
293
|
+
"max_usage": 10, # max number of uses
|
|
294
|
+
"validity_in_min": 10 # token expiration time (minutes)
|
|
295
|
+
}
|
|
296
|
+
partners = ["id::cell", "id::cell"]
|
|
297
|
+
contractID = cell.create_contract(descr, details, partners)
|
|
261
298
|
```
|
|
262
299
|
|
|
263
|
-
|
|
264
|
-
```python
|
|
265
|
-
|
|
266
|
-
cell.
|
|
300
|
+
Sign a Contract:
|
|
301
|
+
```python
|
|
302
|
+
contractID = "id::contract" # select contract
|
|
303
|
+
token = cell.sign_contract(contractID)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Request a Token from another Cell to authorize a service:
|
|
307
|
+
```python
|
|
308
|
+
cp = "id::cell" # select counterparty cell
|
|
309
|
+
contractID = "id::contract" # select contract
|
|
310
|
+
cell.request_token(cp, contractID)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Present a Token to another Cell to authorize a service:
|
|
314
|
+
```python
|
|
315
|
+
token = "token" # select token
|
|
316
|
+
cp = "id::cell" # select counterparty cell
|
|
317
|
+
contractID = "id::contract" # select the contract
|
|
318
|
+
cell.present_token(token, cp, contractID)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Validate a Token to authorize a service:
|
|
322
|
+
```python
|
|
323
|
+
token = "token" # select token
|
|
324
|
+
cp = "id::cell" # select counterparty cell
|
|
325
|
+
contractID = "id::contract" # select contract
|
|
326
|
+
cell.validate_token(token, cp, contractID)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
List Contracts your Cell can interact with:
|
|
330
|
+
```python
|
|
331
|
+
contractList = cell.list_contracts()
|
|
267
332
|
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cli/main.py,sha256=wD5wj2qy-VKwrx9CWoHbxmERSO1Z11B59oMJc49GM9E,9449
|
|
3
|
+
neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
|
|
4
|
+
neuronum/neuronum.py,sha256=qJqYpVoKdUw0YOa7aMp85QSOflkn8R7sqF5dIlTkBe0,16993
|
|
5
|
+
neuronum-1.6.0.dist-info/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
|
|
6
|
+
neuronum-1.6.0.dist-info/METADATA,sha256=BblXzU3CeyyrTzdEyj0K--RnillyBYhNi-61mao50HA,13089
|
|
7
|
+
neuronum-1.6.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
8
|
+
neuronum-1.6.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
9
|
+
neuronum-1.6.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
|
|
10
|
+
neuronum-1.6.0.dist-info/RECORD,,
|
neuronum-1.5.1.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
|
|
2
|
-
neuronum/neuronum.py,sha256=AL0zXiULx-R-Co4XyYtL0lF-z7GGqXGXDxQEYgithPY,14363
|
|
3
|
-
neuronum-1.5.1.dist-info/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
|
|
4
|
-
neuronum-1.5.1.dist-info/METADATA,sha256=H3UZ6u7BHgUcngCTf_0xDwcHjIR1EBlazKe38rXkqnc,11212
|
|
5
|
-
neuronum-1.5.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
6
|
-
neuronum-1.5.1.dist-info/top_level.txt,sha256=73zXVVO9UTTiwEcSaXytsJ8n0q47OCwAqPlIh-hzWJU,9
|
|
7
|
-
neuronum-1.5.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|