hippius 0.1.0__py3-none-any.whl → 0.1.7__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.
- {hippius-0.1.0.dist-info → hippius-0.1.7.dist-info}/METADATA +386 -4
- hippius-0.1.7.dist-info/RECORD +10 -0
- hippius_sdk/__init__.py +45 -1
- hippius_sdk/cli.py +1509 -35
- hippius_sdk/client.py +187 -22
- hippius_sdk/config.py +744 -0
- hippius_sdk/ipfs.py +719 -42
- hippius_sdk/substrate.py +130 -68
- hippius-0.1.0.dist-info/RECORD +0 -9
- {hippius-0.1.0.dist-info → hippius-0.1.7.dist-info}/WHEEL +0 -0
- {hippius-0.1.0.dist-info → hippius-0.1.7.dist-info}/entry_points.txt +0 -0
hippius_sdk/client.py
CHANGED
@@ -3,9 +3,13 @@ Main client for the Hippius SDK.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import os
|
6
|
-
from typing import Dict, Any, Optional, List, Union
|
6
|
+
from typing import Dict, Any, Optional, List, Union, Tuple, Set
|
7
7
|
from hippius_sdk.ipfs import IPFSClient
|
8
8
|
from hippius_sdk.substrate import SubstrateClient, FileInput
|
9
|
+
from hippius_sdk.config import (
|
10
|
+
get_config_value,
|
11
|
+
get_encryption_key,
|
12
|
+
)
|
9
13
|
|
10
14
|
|
11
15
|
class HippiusClient:
|
@@ -17,10 +21,12 @@ class HippiusClient:
|
|
17
21
|
|
18
22
|
def __init__(
|
19
23
|
self,
|
20
|
-
ipfs_gateway: str =
|
21
|
-
ipfs_api_url: str =
|
22
|
-
substrate_url: str = None,
|
23
|
-
substrate_seed_phrase: str = None,
|
24
|
+
ipfs_gateway: Optional[str] = None,
|
25
|
+
ipfs_api_url: Optional[str] = None,
|
26
|
+
substrate_url: Optional[str] = None,
|
27
|
+
substrate_seed_phrase: Optional[str] = None,
|
28
|
+
seed_phrase_password: Optional[str] = None,
|
29
|
+
account_name: Optional[str] = None,
|
24
30
|
encrypt_by_default: Optional[bool] = None,
|
25
31
|
encryption_key: Optional[bytes] = None,
|
26
32
|
):
|
@@ -28,14 +34,46 @@ class HippiusClient:
|
|
28
34
|
Initialize the Hippius client.
|
29
35
|
|
30
36
|
Args:
|
31
|
-
ipfs_gateway: IPFS gateway URL for downloading content
|
32
|
-
ipfs_api_url: IPFS API URL for uploading content
|
33
|
-
substrate_url: WebSocket URL of the Hippius substrate node
|
34
|
-
substrate_seed_phrase: Seed phrase for Substrate account
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
ipfs_gateway: IPFS gateway URL for downloading content (from config if None)
|
38
|
+
ipfs_api_url: IPFS API URL for uploading content (from config if None)
|
39
|
+
substrate_url: WebSocket URL of the Hippius substrate node (from config if None)
|
40
|
+
substrate_seed_phrase: Seed phrase for Substrate account (from config if None)
|
41
|
+
seed_phrase_password: Password to decrypt the seed phrase if it's encrypted
|
42
|
+
account_name: Name of the account to use (uses active account if None)
|
43
|
+
encrypt_by_default: Whether to encrypt files by default (from config if None)
|
44
|
+
encryption_key: Encryption key for NaCl secretbox (from config if None)
|
45
|
+
"""
|
46
|
+
# Load configuration values if not explicitly provided
|
47
|
+
if ipfs_gateway is None:
|
48
|
+
ipfs_gateway = get_config_value("ipfs", "gateway", "https://ipfs.io")
|
49
|
+
|
50
|
+
if ipfs_api_url is None:
|
51
|
+
ipfs_api_url = get_config_value(
|
52
|
+
"ipfs", "api_url", "https://relay-fr.hippius.network"
|
53
|
+
)
|
54
|
+
|
55
|
+
# Check if local IPFS is enabled in config
|
56
|
+
if get_config_value("ipfs", "local_ipfs", False):
|
57
|
+
ipfs_api_url = "http://localhost:5001"
|
58
|
+
|
59
|
+
if substrate_url is None:
|
60
|
+
substrate_url = get_config_value(
|
61
|
+
"substrate", "url", "wss://rpc.hippius.network"
|
62
|
+
)
|
63
|
+
|
64
|
+
if substrate_seed_phrase is None:
|
65
|
+
substrate_seed_phrase = get_config_value("substrate", "seed_phrase")
|
66
|
+
|
67
|
+
if encrypt_by_default is None:
|
68
|
+
encrypt_by_default = get_config_value(
|
69
|
+
"encryption", "encrypt_by_default", False
|
70
|
+
)
|
71
|
+
|
72
|
+
if encryption_key is None:
|
73
|
+
encryption_key = get_encryption_key()
|
74
|
+
|
75
|
+
# Initialize IPFS client
|
76
|
+
self.ipfs_client = IPFSClient(
|
39
77
|
gateway=ipfs_gateway,
|
40
78
|
api_url=ipfs_api_url,
|
41
79
|
encrypt_by_default=encrypt_by_default,
|
@@ -45,7 +83,10 @@ class HippiusClient:
|
|
45
83
|
# Initialize Substrate client
|
46
84
|
try:
|
47
85
|
self.substrate_client = SubstrateClient(
|
48
|
-
url=substrate_url,
|
86
|
+
url=substrate_url,
|
87
|
+
seed_phrase=substrate_seed_phrase,
|
88
|
+
password=seed_phrase_password,
|
89
|
+
account_name=account_name,
|
49
90
|
)
|
50
91
|
except Exception as e:
|
51
92
|
print(f"Warning: Could not initialize Substrate client: {e}")
|
@@ -75,7 +116,7 @@ class HippiusClient:
|
|
75
116
|
ValueError: If encryption is requested but not available
|
76
117
|
"""
|
77
118
|
# Use the enhanced IPFSClient method directly with encryption parameter
|
78
|
-
return self.
|
119
|
+
return self.ipfs_client.upload_file(file_path, encrypt=encrypt)
|
79
120
|
|
80
121
|
def upload_directory(
|
81
122
|
self, dir_path: str, encrypt: Optional[bool] = None
|
@@ -102,7 +143,7 @@ class HippiusClient:
|
|
102
143
|
ValueError: If encryption is requested but not available
|
103
144
|
"""
|
104
145
|
# Use the enhanced IPFSClient method directly with encryption parameter
|
105
|
-
return self.
|
146
|
+
return self.ipfs_client.upload_directory(dir_path, encrypt=encrypt)
|
106
147
|
|
107
148
|
def download_file(
|
108
149
|
self, cid: str, output_path: str, decrypt: Optional[bool] = None
|
@@ -128,7 +169,7 @@ class HippiusClient:
|
|
128
169
|
requests.RequestException: If the download fails
|
129
170
|
ValueError: If decryption is requested but fails
|
130
171
|
"""
|
131
|
-
return self.
|
172
|
+
return self.ipfs_client.download_file(cid, output_path, decrypt=decrypt)
|
132
173
|
|
133
174
|
def cat(
|
134
175
|
self,
|
@@ -155,7 +196,9 @@ class HippiusClient:
|
|
155
196
|
- text_preview/hex_preview: Preview of the content
|
156
197
|
- decrypted: Whether the file was decrypted
|
157
198
|
"""
|
158
|
-
return self.
|
199
|
+
return self.ipfs_client.cat(
|
200
|
+
cid, max_display_bytes, format_output, decrypt=decrypt
|
201
|
+
)
|
159
202
|
|
160
203
|
def exists(self, cid: str) -> Dict[str, Any]:
|
161
204
|
"""
|
@@ -171,7 +214,7 @@ class HippiusClient:
|
|
171
214
|
- formatted_cid: Formatted version of the CID
|
172
215
|
- gateway_url: URL to access the content if it exists
|
173
216
|
"""
|
174
|
-
return self.
|
217
|
+
return self.ipfs_client.exists(cid)
|
175
218
|
|
176
219
|
def pin(self, cid: str) -> Dict[str, Any]:
|
177
220
|
"""
|
@@ -187,7 +230,7 @@ class HippiusClient:
|
|
187
230
|
- formatted_cid: Formatted version of the CID
|
188
231
|
- message: Status message
|
189
232
|
"""
|
190
|
-
return self.
|
233
|
+
return self.ipfs_client.pin(cid)
|
191
234
|
|
192
235
|
def format_cid(self, cid: str) -> str:
|
193
236
|
"""
|
@@ -201,7 +244,7 @@ class HippiusClient:
|
|
201
244
|
Returns:
|
202
245
|
str: Formatted CID string
|
203
246
|
"""
|
204
|
-
return self.
|
247
|
+
return self.ipfs_client.format_cid(cid)
|
205
248
|
|
206
249
|
def format_size(self, size_bytes: int) -> str:
|
207
250
|
"""
|
@@ -215,7 +258,7 @@ class HippiusClient:
|
|
215
258
|
Returns:
|
216
259
|
str: Human-readable size string (e.g., '1.23 MB', '456.78 KB')
|
217
260
|
"""
|
218
|
-
return self.
|
261
|
+
return self.ipfs_client.format_size(size_bytes)
|
219
262
|
|
220
263
|
def generate_encryption_key(self) -> str:
|
221
264
|
"""
|
@@ -244,3 +287,125 @@ class HippiusClient:
|
|
244
287
|
raise ImportError(
|
245
288
|
"PyNaCl is required for encryption. Install it with: pip install pynacl"
|
246
289
|
)
|
290
|
+
|
291
|
+
def erasure_code_file(
|
292
|
+
self,
|
293
|
+
file_path: str,
|
294
|
+
k: int = 3,
|
295
|
+
m: int = 5,
|
296
|
+
chunk_size: int = 1024 * 1024, # 1MB chunks
|
297
|
+
encrypt: Optional[bool] = None,
|
298
|
+
max_retries: int = 3,
|
299
|
+
verbose: bool = True,
|
300
|
+
) -> Dict[str, Any]:
|
301
|
+
"""
|
302
|
+
Split a file using erasure coding, then upload the chunks to IPFS.
|
303
|
+
|
304
|
+
This implements an (m, k) Reed-Solomon code where:
|
305
|
+
- m = total number of chunks
|
306
|
+
- k = minimum chunks needed to reconstruct the file (k <= m)
|
307
|
+
- The file can be reconstructed from any k of the m chunks
|
308
|
+
|
309
|
+
Args:
|
310
|
+
file_path: Path to the file to upload
|
311
|
+
k: Number of data chunks (minimum required to reconstruct)
|
312
|
+
m: Total number of chunks (k + redundancy)
|
313
|
+
chunk_size: Size of each chunk in bytes before encoding
|
314
|
+
encrypt: Whether to encrypt the file before encoding (defaults to self.encrypt_by_default)
|
315
|
+
max_retries: Maximum number of retry attempts for IPFS uploads
|
316
|
+
verbose: Whether to print progress information
|
317
|
+
|
318
|
+
Returns:
|
319
|
+
dict: Metadata including the original file info and chunk information
|
320
|
+
|
321
|
+
Raises:
|
322
|
+
ValueError: If erasure coding is not available or parameters are invalid
|
323
|
+
RuntimeError: If chunk uploads fail
|
324
|
+
"""
|
325
|
+
return self.ipfs_client.erasure_code_file(
|
326
|
+
file_path=file_path,
|
327
|
+
k=k,
|
328
|
+
m=m,
|
329
|
+
chunk_size=chunk_size,
|
330
|
+
encrypt=encrypt,
|
331
|
+
max_retries=max_retries,
|
332
|
+
verbose=verbose,
|
333
|
+
)
|
334
|
+
|
335
|
+
def reconstruct_from_erasure_code(
|
336
|
+
self,
|
337
|
+
metadata_cid: str,
|
338
|
+
output_file: str,
|
339
|
+
temp_dir: str = None,
|
340
|
+
max_retries: int = 3,
|
341
|
+
verbose: bool = True,
|
342
|
+
) -> str:
|
343
|
+
"""
|
344
|
+
Reconstruct a file from erasure-coded chunks using its metadata.
|
345
|
+
|
346
|
+
Args:
|
347
|
+
metadata_cid: IPFS CID of the metadata file
|
348
|
+
output_file: Path where the reconstructed file should be saved
|
349
|
+
temp_dir: Directory to use for temporary files (default: system temp)
|
350
|
+
max_retries: Maximum number of retry attempts for IPFS downloads
|
351
|
+
verbose: Whether to print progress information
|
352
|
+
|
353
|
+
Returns:
|
354
|
+
str: Path to the reconstructed file
|
355
|
+
|
356
|
+
Raises:
|
357
|
+
ValueError: If reconstruction fails
|
358
|
+
RuntimeError: If not enough chunks can be downloaded
|
359
|
+
"""
|
360
|
+
return self.ipfs_client.reconstruct_from_erasure_code(
|
361
|
+
metadata_cid=metadata_cid,
|
362
|
+
output_file=output_file,
|
363
|
+
temp_dir=temp_dir,
|
364
|
+
max_retries=max_retries,
|
365
|
+
verbose=verbose,
|
366
|
+
)
|
367
|
+
|
368
|
+
def store_erasure_coded_file(
|
369
|
+
self,
|
370
|
+
file_path: str,
|
371
|
+
k: int = 3,
|
372
|
+
m: int = 5,
|
373
|
+
chunk_size: int = 1024 * 1024, # 1MB chunks
|
374
|
+
encrypt: Optional[bool] = None,
|
375
|
+
miner_ids: List[str] = None,
|
376
|
+
max_retries: int = 3,
|
377
|
+
verbose: bool = True,
|
378
|
+
) -> Dict[str, Any]:
|
379
|
+
"""
|
380
|
+
Erasure code a file, upload the chunks to IPFS, and store in the Hippius marketplace.
|
381
|
+
|
382
|
+
This is a convenience method that combines erasure_code_file with storage_request.
|
383
|
+
|
384
|
+
Args:
|
385
|
+
file_path: Path to the file to upload
|
386
|
+
k: Number of data chunks (minimum required to reconstruct)
|
387
|
+
m: Total number of chunks (k + redundancy)
|
388
|
+
chunk_size: Size of each chunk in bytes before encoding
|
389
|
+
encrypt: Whether to encrypt the file before encoding
|
390
|
+
miner_ids: List of specific miner IDs to use for storage
|
391
|
+
max_retries: Maximum number of retry attempts
|
392
|
+
verbose: Whether to print progress information
|
393
|
+
|
394
|
+
Returns:
|
395
|
+
dict: Result including metadata CID and transaction hash
|
396
|
+
|
397
|
+
Raises:
|
398
|
+
ValueError: If parameters are invalid
|
399
|
+
RuntimeError: If processing fails
|
400
|
+
"""
|
401
|
+
return self.ipfs_client.store_erasure_coded_file(
|
402
|
+
file_path=file_path,
|
403
|
+
k=k,
|
404
|
+
m=m,
|
405
|
+
chunk_size=chunk_size,
|
406
|
+
encrypt=encrypt,
|
407
|
+
miner_ids=miner_ids,
|
408
|
+
substrate_client=self.substrate_client,
|
409
|
+
max_retries=max_retries,
|
410
|
+
verbose=verbose,
|
411
|
+
)
|