hippius 0.2.39__tar.gz → 0.2.40__tar.gz
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.2.39 → hippius-0.2.40}/PKG-INFO +1 -1
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/__init__.py +1 -1
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/client.py +6 -1
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/ipfs.py +30 -16
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/ipfs_core.py +9 -4
- {hippius-0.2.39 → hippius-0.2.40}/pyproject.toml +1 -1
- {hippius-0.2.39 → hippius-0.2.40}/README.md +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/cli.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/cli_assets.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/cli_handlers.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/cli_parser.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/cli_rich.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/config.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db/README.md +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db/env.db.template +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db/migrations/20241201000001_create_key_storage_tables.sql +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db/migrations/20241202000001_switch_to_subaccount_encryption.sql +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db/setup_database.sh +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/db_utils.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/errors.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/key_storage.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/substrate.py +0 -0
- {hippius-0.2.39 → hippius-0.2.40}/hippius_sdk/utils.py +0 -0
@@ -26,7 +26,7 @@ from hippius_sdk.config import (
|
|
26
26
|
from hippius_sdk.ipfs import IPFSClient, S3PublishResult, S3DownloadResult
|
27
27
|
from hippius_sdk.utils import format_cid, format_size, hex_to_ipfs_cid
|
28
28
|
|
29
|
-
__version__ = "0.2.
|
29
|
+
__version__ = "0.2.40"
|
30
30
|
__all__ = [
|
31
31
|
"HippiusClient",
|
32
32
|
"IPFSClient",
|
@@ -118,7 +118,9 @@ class HippiusClient:
|
|
118
118
|
"""
|
119
119
|
# Use the enhanced IPFSClient method directly with encryption parameter
|
120
120
|
return await self.ipfs_client.upload_file(
|
121
|
-
file_path,
|
121
|
+
file_path,
|
122
|
+
encrypt=encrypt,
|
123
|
+
seed_phrase=seed_phrase,
|
122
124
|
)
|
123
125
|
|
124
126
|
async def upload_directory(
|
@@ -522,6 +524,7 @@ class HippiusClient:
|
|
522
524
|
seed_phrase: str,
|
523
525
|
subaccount_id: str,
|
524
526
|
bucket_name: str,
|
527
|
+
file_name: str = None,
|
525
528
|
store_node: str = "http://localhost:5001",
|
526
529
|
pin_node: str = "https://store.hippius.network",
|
527
530
|
substrate_url: str = "wss://rpc.hippius.network",
|
@@ -535,6 +538,7 @@ class HippiusClient:
|
|
535
538
|
2. Pins to pin_node (remote) for persistence and backup
|
536
539
|
|
537
540
|
Args:
|
541
|
+
file_name: The original file name.
|
538
542
|
file_path: Path to the file to publish
|
539
543
|
encrypt: Whether to encrypt the file before uploading
|
540
544
|
seed_phrase: Seed phrase for blockchain transaction signing
|
@@ -565,6 +569,7 @@ class HippiusClient:
|
|
565
569
|
pin_node,
|
566
570
|
substrate_url,
|
567
571
|
publish,
|
572
|
+
file_name=file_name,
|
568
573
|
)
|
569
574
|
|
570
575
|
async def s3_download(
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
IPFS operations for the Hippius SDK.
|
3
3
|
"""
|
4
|
+
|
4
5
|
import asyncio
|
5
6
|
import base64
|
6
7
|
import hashlib
|
@@ -129,7 +130,7 @@ class IPFSClient:
|
|
129
130
|
|
130
131
|
try:
|
131
132
|
self.client = AsyncIPFSClient(api_url=api_url, gateway=self.gateway)
|
132
|
-
except httpx.ConnectError
|
133
|
+
except httpx.ConnectError:
|
133
134
|
print(
|
134
135
|
f"Warning: Falling back to local IPFS daemon, but still using gateway={self.gateway}"
|
135
136
|
)
|
@@ -241,6 +242,7 @@ class IPFSClient:
|
|
241
242
|
encrypt: Optional[bool] = None,
|
242
243
|
max_retries: int = 3,
|
243
244
|
seed_phrase: Optional[str] = None,
|
245
|
+
file_name: str = None,
|
244
246
|
) -> Dict[str, Any]:
|
245
247
|
"""
|
246
248
|
Upload a file to IPFS with optional encryption.
|
@@ -251,6 +253,7 @@ class IPFSClient:
|
|
251
253
|
encrypt: Whether to encrypt the file (overrides default)
|
252
254
|
max_retries: Maximum number of retry attempts (default: 3)
|
253
255
|
seed_phrase: Optional seed phrase to use for blockchain interactions (uses config if None)
|
256
|
+
file_name: The original file name
|
254
257
|
|
255
258
|
Returns:
|
256
259
|
Dict[str, Any]: Dictionary containing:
|
@@ -278,7 +281,7 @@ class IPFSClient:
|
|
278
281
|
)
|
279
282
|
|
280
283
|
# Get file info before upload
|
281
|
-
|
284
|
+
file_name = file_name if file_name else os.path.basename(file_path)
|
282
285
|
size_bytes = os.path.getsize(file_path)
|
283
286
|
|
284
287
|
# If encryption is requested, encrypt the file first
|
@@ -303,7 +306,10 @@ class IPFSClient:
|
|
303
306
|
# Use the original file for upload
|
304
307
|
upload_path = file_path
|
305
308
|
|
306
|
-
result = await self.client.add_file(
|
309
|
+
result = await self.client.add_file(
|
310
|
+
upload_path,
|
311
|
+
file_name=file_name,
|
312
|
+
)
|
307
313
|
cid = result["Hash"]
|
308
314
|
|
309
315
|
finally:
|
@@ -314,7 +320,7 @@ class IPFSClient:
|
|
314
320
|
# Format the result
|
315
321
|
result = {
|
316
322
|
"cid": cid,
|
317
|
-
"filename":
|
323
|
+
"filename": file_name,
|
318
324
|
"size_bytes": size_bytes,
|
319
325
|
"encrypted": should_encrypt,
|
320
326
|
}
|
@@ -1411,7 +1417,7 @@ class IPFSClient:
|
|
1411
1417
|
|
1412
1418
|
for i, chunk in enumerate(reconstructed_chunks):
|
1413
1419
|
if verbose and i % 10 == 0:
|
1414
|
-
print(f"Processing chunk {i+1}/{len(reconstructed_chunks)}...")
|
1420
|
+
print(f"Processing chunk {i + 1}/{len(reconstructed_chunks)}...")
|
1415
1421
|
|
1416
1422
|
# For all chunks except the last one, use full chunk size
|
1417
1423
|
if i < len(reconstructed_chunks) - 1:
|
@@ -1750,8 +1756,9 @@ class IPFSClient:
|
|
1750
1756
|
# Record the child files that were processed
|
1751
1757
|
result["child_files"] = child_files
|
1752
1758
|
except Exception as e:
|
1753
|
-
print(
|
1754
|
-
|
1759
|
+
print(
|
1760
|
+
f"Warning: Failed to check if CID is a directory: {e}"
|
1761
|
+
) # Continue with regular file unpin
|
1755
1762
|
|
1756
1763
|
# Now unpin the main file/directory
|
1757
1764
|
if unpin:
|
@@ -1821,7 +1828,8 @@ class IPFSClient:
|
|
1821
1828
|
cancel_from_blockchain: bool = True,
|
1822
1829
|
parallel_limit: int = 20,
|
1823
1830
|
seed_phrase: Optional[str] = None,
|
1824
|
-
metadata_timeout: int = 30,
|
1831
|
+
metadata_timeout: int = 30,
|
1832
|
+
# Timeout in seconds for metadata fetch
|
1825
1833
|
) -> bool:
|
1826
1834
|
"""
|
1827
1835
|
Delete an erasure-coded file, including all its chunks in parallel.
|
@@ -1863,8 +1871,7 @@ class IPFSClient:
|
|
1863
1871
|
except asyncio.TimeoutError:
|
1864
1872
|
print(
|
1865
1873
|
f"Timed out after {metadata_timeout}s waiting for metadata download"
|
1866
|
-
)
|
1867
|
-
# We'll continue with blockchain cancellation even without metadata
|
1874
|
+
) # We'll continue with blockchain cancellation even without metadata
|
1868
1875
|
except json.JSONDecodeError as e:
|
1869
1876
|
# If we can't parse the metadata JSON, record the error but continue
|
1870
1877
|
print(f"Error parsing metadata JSON: {e}")
|
@@ -1969,6 +1976,7 @@ class IPFSClient:
|
|
1969
1976
|
pin_node: str = "https://store.hippius.network",
|
1970
1977
|
substrate_url: str = "wss://rpc.hippius.network",
|
1971
1978
|
publish: bool = True,
|
1979
|
+
file_name: str = None,
|
1972
1980
|
) -> Union[S3PublishResult, S3PublishPin]:
|
1973
1981
|
"""
|
1974
1982
|
Publish a file to IPFS and the Hippius marketplace in one operation.
|
@@ -1993,6 +2001,7 @@ class IPFSClient:
|
|
1993
2001
|
pin_node: IPFS node URL for backup pinning (default: remote service)
|
1994
2002
|
substrate_url: the substrate url to connect to for the storage request
|
1995
2003
|
publish: Whether to publish to blockchain (True) or just upload to IPFS (False)
|
2004
|
+
file_name: The original file name.
|
1996
2005
|
|
1997
2006
|
Returns:
|
1998
2007
|
S3PublishResult: Object containing CID, file info, and transaction hash when publish=True
|
@@ -2089,7 +2098,10 @@ class IPFSClient:
|
|
2089
2098
|
# Step 1: Upload to store_node (local) for immediate availability
|
2090
2099
|
try:
|
2091
2100
|
store_client = AsyncIPFSClient(api_url=store_node)
|
2092
|
-
result = await store_client.add_file(
|
2101
|
+
result = await store_client.add_file(
|
2102
|
+
file_path,
|
2103
|
+
file_name=file_name,
|
2104
|
+
)
|
2093
2105
|
cid = result["Hash"]
|
2094
2106
|
logger.info(f"File uploaded to store node {store_node} with CID: {cid}")
|
2095
2107
|
except Exception as e:
|
@@ -2112,7 +2124,8 @@ class IPFSClient:
|
|
2112
2124
|
try:
|
2113
2125
|
# Pass the seed phrase directly to avoid password prompts for encrypted config
|
2114
2126
|
substrate_client = SubstrateClient(
|
2115
|
-
seed_phrase=seed_phrase,
|
2127
|
+
seed_phrase=seed_phrase,
|
2128
|
+
url=substrate_url,
|
2116
2129
|
)
|
2117
2130
|
logger.info(
|
2118
2131
|
f"Submitting storage request to substrate for file: {filename}, CID: {cid}"
|
@@ -2211,7 +2224,7 @@ class IPFSClient:
|
|
2211
2224
|
download_client = AsyncIPFSClient(api_url=download_node)
|
2212
2225
|
|
2213
2226
|
download_url = f"{download_node.rstrip('/')}/api/v0/cat?arg={cid}"
|
2214
|
-
|
2227
|
+
|
2215
2228
|
# Download file into memory
|
2216
2229
|
file_data = bytearray()
|
2217
2230
|
async with download_client.client.stream("POST", download_url) as response:
|
@@ -2221,7 +2234,9 @@ class IPFSClient:
|
|
2221
2234
|
|
2222
2235
|
# Convert to bytes for consistency
|
2223
2236
|
file_data = bytes(file_data)
|
2224
|
-
logger.info(
|
2237
|
+
logger.info(
|
2238
|
+
f"File downloaded from {download_node} with CID: {cid} ({len(file_data)} bytes)"
|
2239
|
+
)
|
2225
2240
|
|
2226
2241
|
except Exception as e:
|
2227
2242
|
raise HippiusIPFSError(
|
@@ -2299,8 +2314,7 @@ class IPFSClient:
|
|
2299
2314
|
except Exception as decrypt_error:
|
2300
2315
|
logger.debug(
|
2301
2316
|
f"Decryption failed with stored key: {decrypt_error}"
|
2302
|
-
)
|
2303
|
-
# Continue to try fallback decryption
|
2317
|
+
) # Continue to try fallback decryption
|
2304
2318
|
else:
|
2305
2319
|
logger.debug(
|
2306
2320
|
"No encryption key found for account+bucket combination"
|
@@ -48,11 +48,16 @@ class AsyncIPFSClient:
|
|
48
48
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
49
49
|
await self.close()
|
50
50
|
|
51
|
-
async def add_file(
|
51
|
+
async def add_file(
|
52
|
+
self,
|
53
|
+
file_path: str,
|
54
|
+
file_name: str = None,
|
55
|
+
) -> Dict[str, Any]:
|
52
56
|
"""
|
53
57
|
Add a file to IPFS.
|
54
58
|
|
55
59
|
Args:
|
60
|
+
file_name: Name of the file
|
56
61
|
file_path: Path to the file to add
|
57
62
|
|
58
63
|
Returns:
|
@@ -60,9 +65,9 @@ class AsyncIPFSClient:
|
|
60
65
|
"""
|
61
66
|
with open(file_path, "rb") as f:
|
62
67
|
file_content = f.read()
|
63
|
-
|
64
|
-
|
65
|
-
|
68
|
+
file_name = file_name if file_name else os.path.basename(file_path)
|
69
|
+
files = {"file": (file_name, file_content, "application/octet-stream")}
|
70
|
+
|
66
71
|
# Explicitly set wrap-with-directory=false to prevent wrapping in directory
|
67
72
|
response = await self.client.post(
|
68
73
|
f"{self.api_url}/api/v0/add?wrap-with-directory=false&cid-version=1",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|