hippius 0.1.14__py3-none-any.whl → 0.2.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.
- {hippius-0.1.14.dist-info → hippius-0.2.0.dist-info}/METADATA +2 -2
- hippius-0.2.0.dist-info/RECORD +12 -0
- hippius_sdk/__init__.py +5 -1
- hippius_sdk/cli.py +397 -47
- hippius_sdk/client.py +20 -22
- hippius_sdk/config.py +19 -26
- hippius_sdk/ipfs.py +62 -408
- hippius_sdk/ipfs_core.py +216 -0
- hippius_sdk/substrate.py +233 -59
- hippius_sdk/utils.py +152 -0
- hippius-0.1.14.dist-info/RECORD +0 -10
- {hippius-0.1.14.dist-info → hippius-0.2.0.dist-info}/WHEEL +0 -0
- {hippius-0.1.14.dist-info → hippius-0.2.0.dist-info}/entry_points.txt +0 -0
hippius_sdk/client.py
CHANGED
@@ -2,12 +2,15 @@
|
|
2
2
|
Main client for the Hippius SDK.
|
3
3
|
"""
|
4
4
|
|
5
|
-
import
|
6
|
-
from typing import Any, Dict, List, Optional
|
5
|
+
import base64
|
6
|
+
from typing import Any, Dict, List, Optional
|
7
|
+
|
8
|
+
import nacl.secret
|
9
|
+
import nacl.utils
|
7
10
|
|
8
11
|
from hippius_sdk.config import get_config_value, get_encryption_key
|
9
12
|
from hippius_sdk.ipfs import IPFSClient
|
10
|
-
from hippius_sdk.substrate import
|
13
|
+
from hippius_sdk.substrate import SubstrateClient
|
11
14
|
|
12
15
|
|
13
16
|
class HippiusClient:
|
@@ -90,7 +93,7 @@ class HippiusClient:
|
|
90
93
|
print(f"Warning: Could not initialize Substrate client: {e}")
|
91
94
|
self.substrate_client = None
|
92
95
|
|
93
|
-
def upload_file(
|
96
|
+
async def upload_file(
|
94
97
|
self, file_path: str, encrypt: Optional[bool] = None
|
95
98
|
) -> Dict[str, Any]:
|
96
99
|
"""
|
@@ -114,9 +117,9 @@ class HippiusClient:
|
|
114
117
|
ValueError: If encryption is requested but not available
|
115
118
|
"""
|
116
119
|
# Use the enhanced IPFSClient method directly with encryption parameter
|
117
|
-
return self.ipfs_client.upload_file(file_path, encrypt=encrypt)
|
120
|
+
return await self.ipfs_client.upload_file(file_path, encrypt=encrypt)
|
118
121
|
|
119
|
-
def upload_directory(
|
122
|
+
async def upload_directory(
|
120
123
|
self, dir_path: str, encrypt: Optional[bool] = None
|
121
124
|
) -> Dict[str, Any]:
|
122
125
|
"""
|
@@ -141,9 +144,9 @@ class HippiusClient:
|
|
141
144
|
ValueError: If encryption is requested but not available
|
142
145
|
"""
|
143
146
|
# Use the enhanced IPFSClient method directly with encryption parameter
|
144
|
-
return self.ipfs_client.upload_directory(dir_path, encrypt=encrypt)
|
147
|
+
return await self.ipfs_client.upload_directory(dir_path, encrypt=encrypt)
|
145
148
|
|
146
|
-
def download_file(
|
149
|
+
async def download_file(
|
147
150
|
self, cid: str, output_path: str, decrypt: Optional[bool] = None
|
148
151
|
) -> Dict[str, Any]:
|
149
152
|
"""
|
@@ -167,9 +170,9 @@ class HippiusClient:
|
|
167
170
|
requests.RequestException: If the download fails
|
168
171
|
ValueError: If decryption is requested but fails
|
169
172
|
"""
|
170
|
-
return self.ipfs_client.download_file(cid, output_path, decrypt=decrypt)
|
173
|
+
return await self.ipfs_client.download_file(cid, output_path, decrypt=decrypt)
|
171
174
|
|
172
|
-
def cat(
|
175
|
+
async def cat(
|
173
176
|
self,
|
174
177
|
cid: str,
|
175
178
|
max_display_bytes: int = 1024,
|
@@ -194,7 +197,7 @@ class HippiusClient:
|
|
194
197
|
- text_preview/hex_preview: Preview of the content
|
195
198
|
- decrypted: Whether the file was decrypted
|
196
199
|
"""
|
197
|
-
return self.ipfs_client.cat(
|
200
|
+
return await self.ipfs_client.cat(
|
198
201
|
cid, max_display_bytes, format_output, decrypt=decrypt
|
199
202
|
)
|
200
203
|
|
@@ -270,11 +273,6 @@ class HippiusClient:
|
|
270
273
|
ImportError: If PyNaCl is not installed
|
271
274
|
"""
|
272
275
|
try:
|
273
|
-
import base64
|
274
|
-
|
275
|
-
import nacl.secret
|
276
|
-
import nacl.utils
|
277
|
-
|
278
276
|
# Generate a random key
|
279
277
|
key = nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)
|
280
278
|
|
@@ -287,7 +285,7 @@ class HippiusClient:
|
|
287
285
|
"PyNaCl is required for encryption. Install it with: pip install pynacl"
|
288
286
|
)
|
289
287
|
|
290
|
-
def erasure_code_file(
|
288
|
+
async def erasure_code_file(
|
291
289
|
self,
|
292
290
|
file_path: str,
|
293
291
|
k: int = 3,
|
@@ -321,7 +319,7 @@ class HippiusClient:
|
|
321
319
|
ValueError: If erasure coding is not available or parameters are invalid
|
322
320
|
RuntimeError: If chunk uploads fail
|
323
321
|
"""
|
324
|
-
return self.ipfs_client.erasure_code_file(
|
322
|
+
return await self.ipfs_client.erasure_code_file(
|
325
323
|
file_path=file_path,
|
326
324
|
k=k,
|
327
325
|
m=m,
|
@@ -331,7 +329,7 @@ class HippiusClient:
|
|
331
329
|
verbose=verbose,
|
332
330
|
)
|
333
331
|
|
334
|
-
def reconstruct_from_erasure_code(
|
332
|
+
async def reconstruct_from_erasure_code(
|
335
333
|
self,
|
336
334
|
metadata_cid: str,
|
337
335
|
output_file: str,
|
@@ -356,7 +354,7 @@ class HippiusClient:
|
|
356
354
|
ValueError: If reconstruction fails
|
357
355
|
RuntimeError: If not enough chunks can be downloaded
|
358
356
|
"""
|
359
|
-
return self.ipfs_client.reconstruct_from_erasure_code(
|
357
|
+
return await self.ipfs_client.reconstruct_from_erasure_code(
|
360
358
|
metadata_cid=metadata_cid,
|
361
359
|
output_file=output_file,
|
362
360
|
temp_dir=temp_dir,
|
@@ -364,7 +362,7 @@ class HippiusClient:
|
|
364
362
|
verbose=verbose,
|
365
363
|
)
|
366
364
|
|
367
|
-
def store_erasure_coded_file(
|
365
|
+
async def store_erasure_coded_file(
|
368
366
|
self,
|
369
367
|
file_path: str,
|
370
368
|
k: int = 3,
|
@@ -397,7 +395,7 @@ class HippiusClient:
|
|
397
395
|
ValueError: If parameters are invalid
|
398
396
|
RuntimeError: If processing fails
|
399
397
|
"""
|
400
|
-
return self.ipfs_client.store_erasure_coded_file(
|
398
|
+
return await self.ipfs_client.store_erasure_coded_file(
|
401
399
|
file_path=file_path,
|
402
400
|
k=k,
|
403
401
|
m=m,
|
hippius_sdk/config.py
CHANGED
@@ -7,11 +7,16 @@ specifically in ~/.hippius/config.
|
|
7
7
|
|
8
8
|
import base64
|
9
9
|
import getpass
|
10
|
-
import hashlib
|
11
10
|
import json
|
12
11
|
import os
|
13
|
-
from
|
14
|
-
|
12
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
13
|
+
|
14
|
+
import nacl.secret
|
15
|
+
import nacl.utils
|
16
|
+
from cryptography.hazmat.primitives import hashes
|
17
|
+
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
18
|
+
from dotenv import load_dotenv
|
19
|
+
from substrateinterface import Keypair
|
15
20
|
|
16
21
|
# Define constants
|
17
22
|
CONFIG_DIR = os.path.expanduser("~/.hippius")
|
@@ -84,7 +89,7 @@ def load_config() -> Dict[str, Any]:
|
|
84
89
|
return config
|
85
90
|
except Exception as e:
|
86
91
|
print(f"Warning: Could not load configuration file: {e}")
|
87
|
-
print(
|
92
|
+
print("Using default configuration")
|
88
93
|
return DEFAULT_CONFIG.copy()
|
89
94
|
|
90
95
|
|
@@ -194,12 +199,10 @@ def _derive_key_from_password(
|
|
194
199
|
Returns:
|
195
200
|
Tuple[bytes, bytes]: (derived_key, salt)
|
196
201
|
"""
|
197
|
-
# Import cryptography for PBKDF2
|
198
202
|
try:
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
203
|
+
# Verify PBKDF2HMAC is already imported at the top
|
204
|
+
if not PBKDF2HMAC:
|
205
|
+
raise ImportError("PBKDF2HMAC not available")
|
203
206
|
except ImportError:
|
204
207
|
raise ImportError(
|
205
208
|
"cryptography is required for password-based encryption. Install it with: pip install cryptography"
|
@@ -238,10 +241,10 @@ def encrypt_with_password(data: str, password: str) -> Tuple[str, str]:
|
|
238
241
|
# Derive key from password with a new salt
|
239
242
|
key, salt = _derive_key_from_password(password)
|
240
243
|
|
241
|
-
#
|
244
|
+
# Verify NaCl is available (imported at the top)
|
242
245
|
try:
|
243
|
-
|
244
|
-
|
246
|
+
if not hasattr(nacl, "secret") or not hasattr(nacl, "utils"):
|
247
|
+
raise ImportError("NaCl modules not available")
|
245
248
|
except ImportError:
|
246
249
|
raise ValueError(
|
247
250
|
"PyNaCl is required for encryption. Install it with: pip install pynacl"
|
@@ -283,10 +286,10 @@ def decrypt_with_password(encrypted_data: str, salt: str, password: str) -> str:
|
|
283
286
|
# Derive the key from the password and salt
|
284
287
|
key, _ = _derive_key_from_password(password, salt_bytes)
|
285
288
|
|
286
|
-
#
|
289
|
+
# Verify NaCl is available (imported at the top)
|
287
290
|
try:
|
288
|
-
|
289
|
-
|
291
|
+
if not hasattr(nacl, "secret") or not hasattr(nacl, "utils"):
|
292
|
+
raise ImportError("NaCl modules not available")
|
290
293
|
except ImportError:
|
291
294
|
raise ValueError(
|
292
295
|
"PyNaCl is required for decryption. Install it with: pip install pynacl"
|
@@ -334,8 +337,6 @@ def encrypt_seed_phrase(
|
|
334
337
|
# Get the SS58 address from the seed phrase
|
335
338
|
ss58_address = None
|
336
339
|
try:
|
337
|
-
from substrateinterface import Keypair
|
338
|
-
|
339
340
|
keypair = Keypair.create_from_mnemonic(seed_phrase)
|
340
341
|
ss58_address = keypair.ss58_address
|
341
342
|
except Exception as e:
|
@@ -514,8 +515,6 @@ def set_seed_phrase(
|
|
514
515
|
# Get the SS58 address from the seed phrase
|
515
516
|
ss58_address = None
|
516
517
|
try:
|
517
|
-
from substrateinterface import Keypair
|
518
|
-
|
519
518
|
keypair = Keypair.create_from_mnemonic(seed_phrase)
|
520
519
|
ss58_address = keypair.ss58_address
|
521
520
|
except Exception as e:
|
@@ -670,13 +669,7 @@ def initialize_from_env() -> None:
|
|
670
669
|
|
671
670
|
This is useful for maintaining backward compatibility with .env files.
|
672
671
|
"""
|
673
|
-
|
674
|
-
try:
|
675
|
-
from dotenv import load_dotenv
|
676
|
-
|
677
|
-
load_dotenv()
|
678
|
-
except ImportError:
|
679
|
-
pass
|
672
|
+
load_dotenv()
|
680
673
|
|
681
674
|
config = load_config()
|
682
675
|
changed = False
|