neuronum 1.5.1__py3-none-any.whl → 1.7.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 +589 -0
- neuronum/neuronum.py +145 -90
- {neuronum-1.5.1.dist-info → neuronum-1.7.0.dist-info}/METADATA +124 -49
- neuronum-1.7.0.dist-info/RECORD +10 -0
- neuronum-1.7.0.dist-info/entry_points.txt +2 -0
- {neuronum-1.5.1.dist-info → neuronum-1.7.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.7.0.dist-info}/LICENSE +0 -0
- {neuronum-1.5.1.dist-info → neuronum-1.7.0.dist-info}/WHEEL +0 -0
cli/__init__.py
ADDED
|
File without changes
|
cli/main.py
ADDED
|
@@ -0,0 +1,589 @@
|
|
|
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 create_cell():
|
|
17
|
+
cell_type = questionary.select(
|
|
18
|
+
"Choose Cell type:",
|
|
19
|
+
choices=["business", "community"]
|
|
20
|
+
).ask()
|
|
21
|
+
|
|
22
|
+
network = questionary.select(
|
|
23
|
+
"Choose Network:",
|
|
24
|
+
choices=["neuronum.net"]
|
|
25
|
+
).ask()
|
|
26
|
+
|
|
27
|
+
if cell_type == "business":
|
|
28
|
+
click.echo("Visit https://neuronum.net/createcell to create your Neuronum Business Cell")
|
|
29
|
+
|
|
30
|
+
if cell_type == "community":
|
|
31
|
+
|
|
32
|
+
email = click.prompt("Enter email")
|
|
33
|
+
password = click.prompt("Enter password", hide_input=True)
|
|
34
|
+
repeat_password = click.prompt("Repeat password", hide_input=True)
|
|
35
|
+
|
|
36
|
+
if password != repeat_password:
|
|
37
|
+
click.echo("Passwords do not match!")
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
url = f"https://{network}/api/create_cell/{cell_type}"
|
|
41
|
+
|
|
42
|
+
create_cell = {"email": email, "password": password}
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
response = requests.post(url, json=create_cell)
|
|
46
|
+
response.raise_for_status()
|
|
47
|
+
status = response.json()["status"]
|
|
48
|
+
|
|
49
|
+
except requests.exceptions.RequestException as e:
|
|
50
|
+
click.echo(f"Error sending request: {e}")
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
if status == True:
|
|
54
|
+
host = response.json()["host"]
|
|
55
|
+
cellkey = click.prompt(f"Please verify your email address with the Cell Key send to {email}")
|
|
56
|
+
|
|
57
|
+
url = f"https://{network}/api/verify_email"
|
|
58
|
+
|
|
59
|
+
verify_email = {"host": host, "email": email, "cellkey": cellkey}
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
response = requests.post(url, json=verify_email)
|
|
63
|
+
response.raise_for_status()
|
|
64
|
+
status = response.json()["status"]
|
|
65
|
+
|
|
66
|
+
except requests.exceptions.RequestException as e:
|
|
67
|
+
click.echo(f"Error sending request: {e}")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
if status == True:
|
|
71
|
+
synapse = response.json()["synapse"]
|
|
72
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
73
|
+
credentials_folder_path.mkdir(parents=True, exist_ok=True)
|
|
74
|
+
|
|
75
|
+
env_path = credentials_folder_path / ".env"
|
|
76
|
+
env_path.write_text(f"HOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
77
|
+
|
|
78
|
+
click.echo(f"Welcome to Neuronum! Community Cell '{host}' created and connected!")
|
|
79
|
+
|
|
80
|
+
if status == False:
|
|
81
|
+
click.echo(f"Error:'{email}' already assigned!")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@click.command()
|
|
86
|
+
def connect_cell():
|
|
87
|
+
email = click.prompt("Enter your Email")
|
|
88
|
+
password = click.prompt("Enter password", hide_input=True)
|
|
89
|
+
|
|
90
|
+
network = questionary.select(
|
|
91
|
+
"Choose Network:",
|
|
92
|
+
choices=["neuronum.net"]
|
|
93
|
+
).ask()
|
|
94
|
+
|
|
95
|
+
url = f"https://{network}/api/connect_cell"
|
|
96
|
+
payload = {"email": email, "password": password}
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
response = requests.post(url, json=payload)
|
|
100
|
+
response.raise_for_status()
|
|
101
|
+
status = response.json()["status"]
|
|
102
|
+
host = response.json()["host"]
|
|
103
|
+
except requests.exceptions.RequestException as e:
|
|
104
|
+
click.echo(f"Error connecting: {e}")
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
if status == True:
|
|
108
|
+
cellkey = click.prompt(f"Please verify your email address with the Cell Key send to {email}")
|
|
109
|
+
url = f"https://{network}/api/verify_email"
|
|
110
|
+
verify_email = {"host": host, "email": email, "cellkey": cellkey}
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
response = requests.post(url, json=verify_email)
|
|
114
|
+
response.raise_for_status()
|
|
115
|
+
status = response.json()["status"]
|
|
116
|
+
synapse = response.json()["synapse"]
|
|
117
|
+
|
|
118
|
+
except requests.exceptions.RequestException as e:
|
|
119
|
+
click.echo(f"Error sending request: {e}")
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
if status == True:
|
|
123
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
124
|
+
credentials_folder_path.mkdir(parents=True, exist_ok=True)
|
|
125
|
+
|
|
126
|
+
env_path = credentials_folder_path / f".env"
|
|
127
|
+
env_path.write_text(f"HOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
128
|
+
|
|
129
|
+
click.echo(f"Cell '{host}' connected!")
|
|
130
|
+
else:
|
|
131
|
+
click.echo(f"Connection failed!")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@click.command()
|
|
135
|
+
def view_cell():
|
|
136
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
137
|
+
env_path = credentials_folder_path / ".env"
|
|
138
|
+
|
|
139
|
+
env_data = {}
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
with open(env_path, "r") as f:
|
|
143
|
+
for line in f:
|
|
144
|
+
key, value = line.strip().split("=")
|
|
145
|
+
env_data[key] = value
|
|
146
|
+
|
|
147
|
+
host = env_data.get("HOST", "")
|
|
148
|
+
|
|
149
|
+
except FileNotFoundError:
|
|
150
|
+
click.echo("Error: No credentials found. Please connect to a cell first.")
|
|
151
|
+
return
|
|
152
|
+
except Exception as e:
|
|
153
|
+
click.echo(f"Error reading .env file: {e}")
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
if host:
|
|
157
|
+
click.echo(f"Connected Cell: '{host}'")
|
|
158
|
+
else:
|
|
159
|
+
click.echo("No active cell connection found.")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@click.command()
|
|
163
|
+
def disconnect_cell():
|
|
164
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
165
|
+
env_path = credentials_folder_path / ".env"
|
|
166
|
+
|
|
167
|
+
env_data = {}
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
with open(env_path, "r") as f:
|
|
171
|
+
for line in f:
|
|
172
|
+
key, value = line.strip().split("=")
|
|
173
|
+
env_data[key] = value
|
|
174
|
+
|
|
175
|
+
host = env_data.get("HOST", "")
|
|
176
|
+
|
|
177
|
+
except FileNotFoundError:
|
|
178
|
+
click.echo("Error: .env with credentials not found")
|
|
179
|
+
return
|
|
180
|
+
except Exception as e:
|
|
181
|
+
click.echo(f"Error reading .env file: {e}")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
if env_path.exists():
|
|
185
|
+
if click.confirm(f"Are you sure you want to disconnect Cell '{host}'?", default=True):
|
|
186
|
+
os.remove(env_path)
|
|
187
|
+
click.echo(f"'{host}' disconnected!")
|
|
188
|
+
else:
|
|
189
|
+
click.echo("Disconnect canceled.")
|
|
190
|
+
else:
|
|
191
|
+
click.echo(f"No Neuronum Cell connected!")
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@click.command()
|
|
195
|
+
def delete_cell():
|
|
196
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
197
|
+
env_path = credentials_folder_path / ".env"
|
|
198
|
+
|
|
199
|
+
env_data = {}
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
with open(env_path, "r") as f:
|
|
203
|
+
for line in f:
|
|
204
|
+
key, value = line.strip().split("=")
|
|
205
|
+
env_data[key] = value
|
|
206
|
+
|
|
207
|
+
host = env_data.get("HOST", "")
|
|
208
|
+
password = env_data.get("PASSWORD", "")
|
|
209
|
+
network = env_data.get("NETWORK", "")
|
|
210
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
211
|
+
|
|
212
|
+
except FileNotFoundError:
|
|
213
|
+
click.echo("Error: No cell connected. Connect Cell first to delete")
|
|
214
|
+
return
|
|
215
|
+
except Exception as e:
|
|
216
|
+
click.echo(f"Error reading .env file: {e}")
|
|
217
|
+
return
|
|
218
|
+
|
|
219
|
+
confirm = click.confirm(f" Are you sure you want to delete '{host}'?", default=True)
|
|
220
|
+
if not confirm:
|
|
221
|
+
click.echo("Deletion canceled.")
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
url = f"https://{network}/api/delete_cell"
|
|
225
|
+
payload = {"host": host, "password": password, "synapse": synapse}
|
|
226
|
+
|
|
227
|
+
try:
|
|
228
|
+
response = requests.delete(url, json=payload)
|
|
229
|
+
response.raise_for_status()
|
|
230
|
+
status = response.json()["status"]
|
|
231
|
+
except requests.exceptions.RequestException as e:
|
|
232
|
+
click.echo(f"Error deleting cell: {e}")
|
|
233
|
+
return
|
|
234
|
+
|
|
235
|
+
if status == True:
|
|
236
|
+
env_path = credentials_folder_path / f"{host}.env"
|
|
237
|
+
if env_path.exists():
|
|
238
|
+
os.remove(env_path)
|
|
239
|
+
click.echo("Credentials deleted successfully!")
|
|
240
|
+
click.echo(f"Neuronum Cell '{host}' has been deleted!")
|
|
241
|
+
else:
|
|
242
|
+
click.echo(f"Neuronum Cell '{host}' deletion failed!")
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@click.command()
|
|
246
|
+
@click.option('--sync', default=None, help="Optional stream ID to generate the sync template.")
|
|
247
|
+
def init_node(sync):
|
|
248
|
+
|
|
249
|
+
node_type = questionary.select(
|
|
250
|
+
"Choose Node type:",
|
|
251
|
+
choices=["public", "private"]
|
|
252
|
+
).ask()
|
|
253
|
+
|
|
254
|
+
descr = click.prompt("Node description (max. 25 characters)")
|
|
255
|
+
|
|
256
|
+
stream = sync if sync else "n9gW3LxQcecI::stx"
|
|
257
|
+
|
|
258
|
+
credentials_folder_path = Path.home() / ".neuronum"
|
|
259
|
+
env_path = credentials_folder_path / ".env"
|
|
260
|
+
|
|
261
|
+
env_data = {}
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
with open(env_path, "r") as f:
|
|
265
|
+
for line in f:
|
|
266
|
+
key, value = line.strip().split("=")
|
|
267
|
+
env_data[key] = value
|
|
268
|
+
|
|
269
|
+
host = env_data.get("HOST", "")
|
|
270
|
+
password = env_data.get("PASSWORD", "")
|
|
271
|
+
network = env_data.get("NETWORK", "")
|
|
272
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
273
|
+
|
|
274
|
+
except FileNotFoundError:
|
|
275
|
+
click.echo("No cell connected. Connect your cell with command neuronum connect-cell")
|
|
276
|
+
return
|
|
277
|
+
except Exception as e:
|
|
278
|
+
click.echo(f"Error reading .env file: {e}")
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
cell = neuronum.Cell(
|
|
282
|
+
host=host,
|
|
283
|
+
password=password,
|
|
284
|
+
network=network,
|
|
285
|
+
synapse=synapse
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
tx = cell.list_tx()
|
|
289
|
+
ctx = cell.list_ctx()
|
|
290
|
+
stx = cell.list_stx()
|
|
291
|
+
contracts = cell.list_contracts()
|
|
292
|
+
|
|
293
|
+
url = f"https://{network}/api/init_node/{node_type}"
|
|
294
|
+
|
|
295
|
+
node = {"descr": descr, "host": host, "password": password, "synapse": synapse}
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
response = requests.post(url, json=node)
|
|
299
|
+
response.raise_for_status()
|
|
300
|
+
nodeID = response.json()["nodeID"]
|
|
301
|
+
except requests.exceptions.RequestException as e:
|
|
302
|
+
click.echo(f"Error sending request: {e}")
|
|
303
|
+
return
|
|
304
|
+
|
|
305
|
+
node_filename = "node_" + nodeID.replace("::node", "")
|
|
306
|
+
project_path = Path(node_filename)
|
|
307
|
+
project_path.mkdir(exist_ok=True)
|
|
308
|
+
|
|
309
|
+
env_path = project_path / ".env"
|
|
310
|
+
env_path.write_text(f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
311
|
+
|
|
312
|
+
gitignore_path = project_path / ".gitignore"
|
|
313
|
+
gitignore_path.write_text(f".env\n")
|
|
314
|
+
|
|
315
|
+
tx_path = project_path / "transmitters.json"
|
|
316
|
+
tx_path.write_text(json.dumps(tx, indent=4))
|
|
317
|
+
|
|
318
|
+
ctx_path = project_path / "circuits.json"
|
|
319
|
+
ctx_path.write_text(json.dumps(ctx, indent=4))
|
|
320
|
+
|
|
321
|
+
stx_path = project_path / "streams.json"
|
|
322
|
+
stx_path.write_text(json.dumps(stx, indent=4))
|
|
323
|
+
|
|
324
|
+
contracts_path = project_path / "contracts.json"
|
|
325
|
+
contracts_path.write_text(json.dumps(contracts, indent=4))
|
|
326
|
+
|
|
327
|
+
nodemd_path = project_path / "NODE.md"
|
|
328
|
+
nodemd_path.write_text("""\
|
|
329
|
+
## Use this NODE.md file to add instructions on how to interact with your node
|
|
330
|
+
""")
|
|
331
|
+
|
|
332
|
+
main_path = project_path / "main.py"
|
|
333
|
+
main_path.write_text(f"""\
|
|
334
|
+
import neuronum
|
|
335
|
+
import os
|
|
336
|
+
from dotenv import load_dotenv
|
|
337
|
+
|
|
338
|
+
load_dotenv()
|
|
339
|
+
host = os.getenv("HOST")
|
|
340
|
+
password = os.getenv("PASSWORD")
|
|
341
|
+
network = os.getenv("NETWORK")
|
|
342
|
+
synapse = os.getenv("SYNAPSE")
|
|
343
|
+
|
|
344
|
+
cell = neuronum.Cell(
|
|
345
|
+
host=host,
|
|
346
|
+
password=password,
|
|
347
|
+
network=network,
|
|
348
|
+
synapse=synapse
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
STX = "{stream}"
|
|
352
|
+
stream = cell.sync(STX)
|
|
353
|
+
for operation in stream:
|
|
354
|
+
label = operation.get("label")
|
|
355
|
+
value = operation.get("data").get("message")
|
|
356
|
+
ts = operation.get("time")
|
|
357
|
+
stxID = operation.get("stxID")
|
|
358
|
+
operator = operation.get("operator")
|
|
359
|
+
print(label, value, ts, stxID, operator)
|
|
360
|
+
""")
|
|
361
|
+
|
|
362
|
+
click.echo(f"Neuronum Node '{nodeID}' initialized!")
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@click.command()
|
|
366
|
+
def start_node():
|
|
367
|
+
click.echo("Starting Node...")
|
|
368
|
+
|
|
369
|
+
project_path = Path.cwd()
|
|
370
|
+
main_file = project_path / "main.py"
|
|
371
|
+
|
|
372
|
+
if not main_file.exists():
|
|
373
|
+
click.echo("Error: main.py not found. Make sure the node is set up.")
|
|
374
|
+
return
|
|
375
|
+
|
|
376
|
+
process = subprocess.Popen(["python", str(main_file)], start_new_session=True)
|
|
377
|
+
|
|
378
|
+
with open("node_pid.txt", "w") as f:
|
|
379
|
+
f.write(str(process.pid))
|
|
380
|
+
|
|
381
|
+
click.echo("Node started successfully!")
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
@click.command()
|
|
385
|
+
def stop_node():
|
|
386
|
+
click.echo("Stopping Node...")
|
|
387
|
+
|
|
388
|
+
try:
|
|
389
|
+
with open("node_pid.txt", "r") as f:
|
|
390
|
+
pid = int(f.read().strip())
|
|
391
|
+
os.kill(pid, 9)
|
|
392
|
+
os.remove("node_pid.txt")
|
|
393
|
+
click.echo("Node stopped successfully!")
|
|
394
|
+
except FileNotFoundError:
|
|
395
|
+
click.echo("Error: No active node process found.")
|
|
396
|
+
except Exception as e:
|
|
397
|
+
click.echo(f"Error stopping node: {e}")
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
@click.command()
|
|
401
|
+
def register_node():
|
|
402
|
+
env_data = {}
|
|
403
|
+
try:
|
|
404
|
+
with open(".env", "r") as f:
|
|
405
|
+
for line in f:
|
|
406
|
+
key, value = line.strip().split("=")
|
|
407
|
+
env_data[key] = value
|
|
408
|
+
|
|
409
|
+
nodeID = env_data.get("NODE", "")
|
|
410
|
+
host = env_data.get("HOST", "")
|
|
411
|
+
password = env_data.get("PASSWORD", "")
|
|
412
|
+
network = env_data.get("NETWORK", "")
|
|
413
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
414
|
+
|
|
415
|
+
except FileNotFoundError:
|
|
416
|
+
print("Error: .env with credentials not found")
|
|
417
|
+
return
|
|
418
|
+
except Exception as e:
|
|
419
|
+
print(f"Error reading .env file: {e}")
|
|
420
|
+
return
|
|
421
|
+
|
|
422
|
+
try:
|
|
423
|
+
with open("NODE.md", "r") as f:
|
|
424
|
+
nodemd_file = f.read()
|
|
425
|
+
|
|
426
|
+
except FileNotFoundError:
|
|
427
|
+
print("Error: NODE.md file not found")
|
|
428
|
+
return
|
|
429
|
+
except Exception as e:
|
|
430
|
+
print(f"Error reading NODE.md file: {e}")
|
|
431
|
+
return
|
|
432
|
+
|
|
433
|
+
url = f"https://{network}/api/register_node"
|
|
434
|
+
|
|
435
|
+
node = {
|
|
436
|
+
"nodeID": nodeID,
|
|
437
|
+
"host": host,
|
|
438
|
+
"password": password,
|
|
439
|
+
"synapse": synapse,
|
|
440
|
+
"nodemd_file": nodemd_file
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
try:
|
|
444
|
+
response = requests.post(url, json=node)
|
|
445
|
+
response.raise_for_status()
|
|
446
|
+
nodeID = response.json()["nodeID"]
|
|
447
|
+
node_url = response.json()["node_url"]
|
|
448
|
+
except requests.exceptions.RequestException as e:
|
|
449
|
+
click.echo(f"Error sending request: {e}")
|
|
450
|
+
return
|
|
451
|
+
|
|
452
|
+
click.echo(f"Neuronum Node '{nodeID}' registered! Visit: {node_url}")
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
@click.command()
|
|
456
|
+
def update_node():
|
|
457
|
+
env_data = {}
|
|
458
|
+
try:
|
|
459
|
+
with open(".env", "r") as f:
|
|
460
|
+
for line in f:
|
|
461
|
+
key, value = line.strip().split("=")
|
|
462
|
+
env_data[key] = value
|
|
463
|
+
|
|
464
|
+
nodeID = env_data.get("NODE", "")
|
|
465
|
+
host = env_data.get("HOST", "")
|
|
466
|
+
password = env_data.get("PASSWORD", "")
|
|
467
|
+
network = env_data.get("NETWORK", "")
|
|
468
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
469
|
+
|
|
470
|
+
except FileNotFoundError:
|
|
471
|
+
print("Error: .env with credentials not found")
|
|
472
|
+
return
|
|
473
|
+
except Exception as e:
|
|
474
|
+
print(f"Error reading .env file: {e}")
|
|
475
|
+
return
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
with open("NODE.md", "r") as f:
|
|
479
|
+
nodemd_file = f.read()
|
|
480
|
+
|
|
481
|
+
except FileNotFoundError:
|
|
482
|
+
print("Error: NODE.md file not found")
|
|
483
|
+
return
|
|
484
|
+
except Exception as e:
|
|
485
|
+
print(f"Error reading NODE.md file: {e}")
|
|
486
|
+
return
|
|
487
|
+
|
|
488
|
+
url = f"https://{network}/api/update_node"
|
|
489
|
+
|
|
490
|
+
node = {
|
|
491
|
+
"nodeID": nodeID,
|
|
492
|
+
"host": host,
|
|
493
|
+
"password": password,
|
|
494
|
+
"synapse": synapse,
|
|
495
|
+
"nodemd_file": nodemd_file
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
try:
|
|
499
|
+
response = requests.post(url, json=node)
|
|
500
|
+
response.raise_for_status()
|
|
501
|
+
nodeID = response.json()["nodeID"]
|
|
502
|
+
node_url = response.json()["node_url"]
|
|
503
|
+
except requests.exceptions.RequestException as e:
|
|
504
|
+
click.echo(f"Error sending request: {e}")
|
|
505
|
+
return
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
cell = neuronum.Cell(
|
|
509
|
+
host=host,
|
|
510
|
+
password=password,
|
|
511
|
+
network=network,
|
|
512
|
+
synapse=synapse
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
tx = cell.list_tx()
|
|
516
|
+
ctx = cell.list_ctx()
|
|
517
|
+
stx = cell.list_stx()
|
|
518
|
+
contracts = cell.list_contracts()
|
|
519
|
+
|
|
520
|
+
tx_path = Path("transmitters.json")
|
|
521
|
+
ctx_path = Path("circuits.json")
|
|
522
|
+
stx_path = Path("streams.json")
|
|
523
|
+
contracts_path = Path("contracts.json")
|
|
524
|
+
|
|
525
|
+
tx_path.write_text(json.dumps(tx, indent=4))
|
|
526
|
+
ctx_path.write_text(json.dumps(ctx, indent=4))
|
|
527
|
+
stx_path.write_text(json.dumps(stx, indent=4))
|
|
528
|
+
contracts_path.write_text(json.dumps(contracts, indent=4))
|
|
529
|
+
|
|
530
|
+
click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@click.command()
|
|
534
|
+
def delete_node():
|
|
535
|
+
env_data = {}
|
|
536
|
+
try:
|
|
537
|
+
with open(".env", "r") as f:
|
|
538
|
+
for line in f:
|
|
539
|
+
key, value = line.strip().split("=")
|
|
540
|
+
env_data[key] = value
|
|
541
|
+
|
|
542
|
+
nodeID = env_data.get("NODE", "")
|
|
543
|
+
host = env_data.get("HOST", "")
|
|
544
|
+
password = env_data.get("PASSWORD", "")
|
|
545
|
+
network = env_data.get("NETWORK", "")
|
|
546
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
547
|
+
|
|
548
|
+
except FileNotFoundError:
|
|
549
|
+
print("Error: .env with credentials not found")
|
|
550
|
+
return
|
|
551
|
+
except Exception as e:
|
|
552
|
+
print(f"Error reading .env file: {e}")
|
|
553
|
+
return
|
|
554
|
+
|
|
555
|
+
url = f"https://{network}/api/delete_node"
|
|
556
|
+
|
|
557
|
+
node = {
|
|
558
|
+
"nodeID": nodeID,
|
|
559
|
+
"host": host,
|
|
560
|
+
"password": password,
|
|
561
|
+
"synapse": synapse
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
try:
|
|
565
|
+
response = requests.post(url, json=node)
|
|
566
|
+
response.raise_for_status()
|
|
567
|
+
nodeID = response.json()["nodeID"]
|
|
568
|
+
except requests.exceptions.RequestException as e:
|
|
569
|
+
click.echo(f"Error sending request: {e}")
|
|
570
|
+
return
|
|
571
|
+
|
|
572
|
+
click.echo(f"Neuronum Node '{nodeID}' deleted!")
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
cli.add_command(create_cell)
|
|
576
|
+
cli.add_command(connect_cell)
|
|
577
|
+
cli.add_command(view_cell)
|
|
578
|
+
cli.add_command(disconnect_cell)
|
|
579
|
+
cli.add_command(delete_cell)
|
|
580
|
+
cli.add_command(init_node)
|
|
581
|
+
cli.add_command(start_node)
|
|
582
|
+
cli.add_command(stop_node)
|
|
583
|
+
cli.add_command(register_node)
|
|
584
|
+
cli.add_command(update_node)
|
|
585
|
+
cli.add_command(delete_node)
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
if __name__ == "__main__":
|
|
589
|
+
cli()
|
neuronum/neuronum.py
CHANGED
|
@@ -206,130 +206,56 @@ 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:
|
|
314
257
|
print(f"Unexpected error: {e}")
|
|
315
258
|
|
|
316
|
-
|
|
317
|
-
def connect(self):
|
|
318
|
-
url = f"https://{self.network}/api/connect"
|
|
319
|
-
|
|
320
|
-
test = {
|
|
321
|
-
"cell": self.to_dict()
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
try:
|
|
325
|
-
response = requests.post(url, json=test)
|
|
326
|
-
response.raise_for_status()
|
|
327
|
-
print(response.json()["connection"])
|
|
328
|
-
except requests.exceptions.RequestException as e:
|
|
329
|
-
print(f"Error sending request: {e}")
|
|
330
|
-
except Exception as e:
|
|
331
|
-
print(f"Unexpected error: {e}")
|
|
332
|
-
|
|
333
259
|
|
|
334
260
|
def store(self, label: str, data: dict, ctx: Optional[str] = None):
|
|
335
261
|
if ctx:
|
|
@@ -459,14 +385,13 @@ class Cell:
|
|
|
459
385
|
try:
|
|
460
386
|
ws = create_connection(f"wss://{self.network}/sync/{stx}")
|
|
461
387
|
ws.send(json.dumps(auth))
|
|
462
|
-
print("
|
|
388
|
+
print("Listening to Stream...")
|
|
463
389
|
|
|
464
390
|
try:
|
|
465
391
|
while True:
|
|
466
392
|
try:
|
|
467
393
|
raw_operation = ws.recv()
|
|
468
394
|
operation = json.loads(raw_operation)
|
|
469
|
-
print("Listening to Stream...")
|
|
470
395
|
yield operation
|
|
471
396
|
|
|
472
397
|
except socket.timeout:
|
|
@@ -474,17 +399,147 @@ class Cell:
|
|
|
474
399
|
continue
|
|
475
400
|
|
|
476
401
|
except KeyboardInterrupt:
|
|
477
|
-
print("Stream-Synchronization ended!")
|
|
478
|
-
except Exception as e:
|
|
479
|
-
print(f"Error: {e}")
|
|
480
|
-
finally:
|
|
481
402
|
ws.close()
|
|
482
403
|
print("Connection closed.")
|
|
483
|
-
|
|
404
|
+
except Exception as e:
|
|
405
|
+
print(f"Error: {e}")
|
|
406
|
+
|
|
407
|
+
|
|
484
408
|
except KeyboardInterrupt:
|
|
485
409
|
print("Stream-Synchronization ended!")
|
|
486
410
|
ws.close()
|
|
487
411
|
print("Connection closed. Goodbye!")
|
|
488
412
|
|
|
489
413
|
|
|
414
|
+
def sign_contract(self, contractID: str):
|
|
415
|
+
full_url = f"https://{self.network}/api/sign_contract"
|
|
416
|
+
|
|
417
|
+
sign_contract = {
|
|
418
|
+
"contractID": contractID,
|
|
419
|
+
"cell": self.to_dict()
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
try:
|
|
423
|
+
response = requests.post(full_url, json=sign_contract)
|
|
424
|
+
response.raise_for_status()
|
|
425
|
+
return response.json()["token"]
|
|
426
|
+
except requests.exceptions.RequestException as e:
|
|
427
|
+
print(f"Error sending request: {e}")
|
|
428
|
+
except Exception as e:
|
|
429
|
+
print(f"Unexpected error: {e}")
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def validate_token(self, token: str, cp: str, contractID: str):
|
|
433
|
+
full_url = f"https://{self.network}/api/validate_token"
|
|
434
|
+
|
|
435
|
+
validate = {
|
|
436
|
+
"token": token,
|
|
437
|
+
"cp": cp,
|
|
438
|
+
"contractID": contractID,
|
|
439
|
+
"cell": self.to_dict()
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
try:
|
|
443
|
+
response = requests.post(full_url, json=validate)
|
|
444
|
+
response.raise_for_status()
|
|
445
|
+
return response.json()["validity"]
|
|
446
|
+
except requests.exceptions.RequestException as e:
|
|
447
|
+
print(f"Error sending request: {e}")
|
|
448
|
+
except Exception as e:
|
|
449
|
+
print(f"Unexpected error: {e}")
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def request_token(self, cp: str, contractID: str):
|
|
453
|
+
full_url = f"https://{self.network}/api/request_token"
|
|
454
|
+
|
|
455
|
+
request_token = {
|
|
456
|
+
"cp": cp,
|
|
457
|
+
"contractID": contractID,
|
|
458
|
+
"cell": self.to_dict()
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
try:
|
|
462
|
+
response = requests.post(full_url, json=request_token)
|
|
463
|
+
response.raise_for_status()
|
|
464
|
+
print(response.json())
|
|
465
|
+
except requests.exceptions.RequestException as e:
|
|
466
|
+
print(f"Error sending request: {e}")
|
|
467
|
+
except Exception as e:
|
|
468
|
+
print(f"Unexpected error: {e}")
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def present_token(self, token: str, cp: str, contractID: str):
|
|
472
|
+
full_url = f"https://{self.network}/api/present_token"
|
|
473
|
+
|
|
474
|
+
present_token = {
|
|
475
|
+
"token": token,
|
|
476
|
+
"cp": cp,
|
|
477
|
+
"contractID": contractID,
|
|
478
|
+
"cell": self.to_dict()
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
try:
|
|
482
|
+
response = requests.post(full_url, json=present_token)
|
|
483
|
+
response.raise_for_status()
|
|
484
|
+
print(response.json())
|
|
485
|
+
except requests.exceptions.RequestException as e:
|
|
486
|
+
print(f"Error sending request: {e}")
|
|
487
|
+
except Exception as e:
|
|
488
|
+
print(f"Unexpected error: {e}")
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def create_contract(self, descr: str, details: dict, partners: list):
|
|
492
|
+
full_url = f"https://{self.network}/api/create_contract"
|
|
493
|
+
|
|
494
|
+
create_contract = {
|
|
495
|
+
"cell": self.to_dict(),
|
|
496
|
+
"descr": descr,
|
|
497
|
+
"details": details,
|
|
498
|
+
"partners": partners
|
|
499
|
+
}
|
|
500
|
+
try:
|
|
501
|
+
response = requests.post(full_url, json=create_contract)
|
|
502
|
+
response.raise_for_status()
|
|
503
|
+
return response.json()["contractID"]
|
|
504
|
+
except requests.exceptions.RequestException as e:
|
|
505
|
+
print(f"Error sending request: {e}")
|
|
506
|
+
except Exception as e:
|
|
507
|
+
print(f"Unexpected error: {e}")
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def delete_contract(self, contractID: str):
|
|
511
|
+
full_url = f"https://{self.network}/api/delete_contract"
|
|
512
|
+
|
|
513
|
+
request = {
|
|
514
|
+
"cell": self.to_dict(),
|
|
515
|
+
"contractID": contractID
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
try:
|
|
519
|
+
response = requests.post(full_url, json=request)
|
|
520
|
+
response.raise_for_status()
|
|
521
|
+
print(f"Response from Neuronum: {response.json()}")
|
|
522
|
+
except requests.exceptions.RequestException as e:
|
|
523
|
+
print(f"Error sending request: {e}")
|
|
524
|
+
except Exception as e:
|
|
525
|
+
print(f"Unexpected error: {e}")
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
def list_contracts(self):
|
|
529
|
+
full_url = f"https://{self.network}/api/list_contracts"
|
|
530
|
+
|
|
531
|
+
list_contracts = {
|
|
532
|
+
"cell": self.to_dict()
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
try:
|
|
536
|
+
response = requests.post(full_url, json=list_contracts)
|
|
537
|
+
response.raise_for_status()
|
|
538
|
+
return response.json()["Contracts"]
|
|
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
|
+
|
|
490
545
|
__all__ = ['Cell']
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.7.0
|
|
4
|
+
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
7
7
|
Author-email: welcome@neuronum.net
|
|
@@ -9,52 +9,98 @@ Project-URL: GitHub, https://github.com/neuronumcybernetics/neuronum
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
|
-
Requires-Python: >=3.
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
13
|
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
|
+
Build, deploy and automate IoT connectivity with `Neuronum`
|
|
25
26
|
|
|
26
27
|
## Features
|
|
27
|
-
- **Cell**:
|
|
28
|
+
- **Cells/Cell-CLI**: Create and manage Neuronum Cells from the command line
|
|
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 services exchange and authorization between Cells and Nodes
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
### Installation
|
|
36
|
+
Install the Neuronum library using pip:
|
|
37
|
+
```sh
|
|
38
|
+
$ pip install neuronum
|
|
39
|
+
```
|
|
35
40
|
|
|
41
|
+
### Cells/Cell-CLI
|
|
42
|
+
To interact with the Neuronum Network, you must first create a Neuronum Cell
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
pip install neuronum
|
|
44
|
+
Create Cell:
|
|
45
|
+
```sh
|
|
46
|
+
$ neuronum create-cell
|
|
41
47
|
```
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
49
|
+
Connect Cell:
|
|
50
|
+
```sh
|
|
51
|
+
$ neuronum connect-cell
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
View connected Cell:
|
|
55
|
+
```sh
|
|
56
|
+
$ neuronum view-cell
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Disconnect Cell:
|
|
60
|
+
```sh
|
|
61
|
+
$ neuronum disconnect-cell
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Delete Cell:
|
|
65
|
+
```sh
|
|
66
|
+
$ neuronum delete-cell
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Nodes/Node-CLI
|
|
70
|
+
Neuronum Nodes are soft- and hardware components that power the Neuronum Network, enabling seamless communication between Nodes and Cells
|
|
71
|
+
|
|
72
|
+
Initialize a Node:
|
|
73
|
+
```sh
|
|
74
|
+
$ neuronum init-node # neuronum init-node --sync id::stx (optional)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Start a Node:
|
|
78
|
+
```sh
|
|
79
|
+
$ neuronum start-node
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Stop a Node:
|
|
83
|
+
```sh
|
|
84
|
+
$ neuronum stop-node
|
|
85
|
+
```
|
|
46
86
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
87
|
+
Register a Node on the Neuronum Network:
|
|
88
|
+
```sh
|
|
89
|
+
$ neuronum register-node
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Update a Node:
|
|
93
|
+
```sh
|
|
94
|
+
$ neuronum update-node
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Delete a Node:
|
|
98
|
+
```sh
|
|
99
|
+
$ neuronum delete-node
|
|
54
100
|
```
|
|
55
101
|
|
|
56
102
|
### Transmitters (TX)
|
|
57
|
-
Transmitters (TX) are used to create predefined templates to receive and send data in a standardized format
|
|
103
|
+
Transmitters (TX) are used to create predefined templates to receive and send data in a standardized format
|
|
58
104
|
|
|
59
105
|
Create Transmitter (TX):
|
|
60
106
|
```python
|
|
@@ -87,10 +133,9 @@ TX = "id::tx" # select Trans
|
|
|
87
133
|
cell.delete_tx(TX) # delete TX
|
|
88
134
|
```
|
|
89
135
|
|
|
90
|
-
List Transmitter (TX)
|
|
91
|
-
```python
|
|
92
|
-
|
|
93
|
-
txList = cell.list_tx(cellID) # list Transmitters (TX)
|
|
136
|
+
List Transmitter (TX) your Cell can activate:
|
|
137
|
+
```python
|
|
138
|
+
txList = cell.list_tx() # list Transmitters (TX)
|
|
94
139
|
```
|
|
95
140
|
|
|
96
141
|
### Circuits (CTX)
|
|
@@ -177,10 +222,9 @@ CTX = "id::ctx" # select Circu
|
|
|
177
222
|
cell.delete_ctx(CTX) # delete CTX
|
|
178
223
|
```
|
|
179
224
|
|
|
180
|
-
List Circuits (CTX)
|
|
181
|
-
```python
|
|
182
|
-
|
|
183
|
-
ctxList = cell.list_ctx(cellID) # list Circuits (CTX)
|
|
225
|
+
List Circuits (CTX) your Cell can interact with:
|
|
226
|
+
```python
|
|
227
|
+
ctxList = cell.list_ctx() # list Circuits (CTX)
|
|
184
228
|
```
|
|
185
229
|
|
|
186
230
|
### Streams (STX)
|
|
@@ -243,25 +287,56 @@ for operation in stream: # load stream
|
|
|
243
287
|
operator = operation.get("operator")
|
|
244
288
|
```
|
|
245
289
|
|
|
246
|
-
List Streams (STX)
|
|
247
|
-
```python
|
|
248
|
-
|
|
249
|
-
stxList = cell.list_stx(cellID) # list Streams (STX)
|
|
290
|
+
List Streams (STX) your Cell can interact with:
|
|
291
|
+
```python
|
|
292
|
+
stxList = cell.list_stx() # list Streams (STX)
|
|
250
293
|
```
|
|
251
294
|
|
|
252
|
-
###
|
|
253
|
-
|
|
295
|
+
### Contracts/Tokens
|
|
296
|
+
Contracts are predefined token-based rules to automate service exchange and authorization between Cells and Nodes
|
|
254
297
|
|
|
255
|
-
|
|
298
|
+
Create a Contract:
|
|
256
299
|
```python
|
|
257
|
-
descr = "
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
300
|
+
descr = "Test Contract" # short description (max 25 characters)
|
|
301
|
+
details = { # define token details
|
|
302
|
+
"price_in_eur": False, # token price in EUR (int, float or False)
|
|
303
|
+
"max_usage": False, # max number of uses (int or False)
|
|
304
|
+
"validity_in_min": False # token expiration time in min (int, float or False)
|
|
305
|
+
}
|
|
306
|
+
partners = ["id::cell", "id::cell"]
|
|
307
|
+
contractID = cell.create_contract(descr, details, partners)
|
|
261
308
|
```
|
|
262
309
|
|
|
263
|
-
|
|
264
|
-
```python
|
|
265
|
-
|
|
266
|
-
cell.
|
|
310
|
+
Sign a Contract:
|
|
311
|
+
```python
|
|
312
|
+
contractID = "id::contract" # select contract
|
|
313
|
+
token = cell.sign_contract(contractID)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Request a Token from another Cell to authorize a service:
|
|
317
|
+
```python
|
|
318
|
+
cp = "id::cell" # select counterparty cell
|
|
319
|
+
contractID = "id::contract" # select contract
|
|
320
|
+
cell.request_token(cp, contractID)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Present a Token to another Cell to authorize a service:
|
|
324
|
+
```python
|
|
325
|
+
token = "token" # select token
|
|
326
|
+
cp = "id::cell" # select counterparty cell
|
|
327
|
+
contractID = "id::contract" # select the contract
|
|
328
|
+
cell.present_token(token, cp, contractID)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Validate a Token to authorize a service:
|
|
332
|
+
```python
|
|
333
|
+
token = "token" # select token
|
|
334
|
+
cp = "id::cell" # select counterparty cell
|
|
335
|
+
contractID = "id::contract" # select contract
|
|
336
|
+
cell.validate_token(token, cp, contractID)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
List Contracts your Cell can interact with:
|
|
340
|
+
```python
|
|
341
|
+
contractList = cell.list_contracts()
|
|
267
342
|
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cli/main.py,sha256=w4pNMA7ySCKTk4Z-Mb3W7cIw5ZUpLrP92L2HfrcFxSM,17637
|
|
3
|
+
neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
|
|
4
|
+
neuronum/neuronum.py,sha256=4j3fV7VHPb1KcQucOEDBQ-v2SoG9c2WfGPqMfI3OF88,16498
|
|
5
|
+
neuronum-1.7.0.dist-info/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
|
|
6
|
+
neuronum-1.7.0.dist-info/METADATA,sha256=GqgpO0lCzLKJwOfNRH8GzXPbRgsvRvZm3YP5FPVMbNs,12806
|
|
7
|
+
neuronum-1.7.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
8
|
+
neuronum-1.7.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
9
|
+
neuronum-1.7.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
|
|
10
|
+
neuronum-1.7.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
|