hippius 0.2.37__py3-none-any.whl → 0.2.39__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.2.37.dist-info → hippius-0.2.39.dist-info}/METADATA +1 -1
- {hippius-0.2.37.dist-info → hippius-0.2.39.dist-info}/RECORD +7 -7
- hippius_sdk/__init__.py +1 -1
- hippius_sdk/client.py +9 -5
- hippius_sdk/ipfs.py +96 -83
- {hippius-0.2.37.dist-info → hippius-0.2.39.dist-info}/WHEEL +0 -0
- {hippius-0.2.37.dist-info → hippius-0.2.39.dist-info}/entry_points.txt +0 -0
@@ -1,10 +1,10 @@
|
|
1
|
-
hippius_sdk/__init__.py,sha256=
|
1
|
+
hippius_sdk/__init__.py,sha256=YRl6k_zVhkcQus3lgRi_IXvBPDgfvguZlJCtmOcp1CI,1474
|
2
2
|
hippius_sdk/cli.py,sha256=aqKOYSBSWt7UhcpFt7wf9yIPJ3bznpsJ6ehOnuZ4usI,18235
|
3
3
|
hippius_sdk/cli_assets.py,sha256=rjH3Z5A1CQr2d5CIAAAb0WMCjoZZlMWcdo0f93KqluE,635
|
4
4
|
hippius_sdk/cli_handlers.py,sha256=HkZldE8ZDS6WHu8aSoeS_rYZ4kp3F-Kdzu-weY1c0vU,128258
|
5
5
|
hippius_sdk/cli_parser.py,sha256=z7UvgWvvy04ey-R56qZiCqYc_9RaNq1rVDkQyXoK3JU,21100
|
6
6
|
hippius_sdk/cli_rich.py,sha256=_jTBYMdHi2--fIVwoeNi-EtkdOb6Zy_O2TUiGvU3O7s,7324
|
7
|
-
hippius_sdk/client.py,sha256=
|
7
|
+
hippius_sdk/client.py,sha256=yS7fKAYIIjLReoUg1hppCD1sRy5MbSS81aLF_JLIZRE,23275
|
8
8
|
hippius_sdk/config.py,sha256=Hf_aUYzG9ylzqauA_ABUSSB5mBTYbp-VtB36VQt2XDw,21981
|
9
9
|
hippius_sdk/db/README.md,sha256=okDeI1qgkaZqXSlJ8L0xIE4UpuxO-qEGPIbXUvSHQjU,2030
|
10
10
|
hippius_sdk/db/env.db.template,sha256=_6hEC3IvkzCDOAzG1_yJUKRUfCTMciNaJUicZpMCat4,217
|
@@ -13,12 +13,12 @@ hippius_sdk/db/migrations/20241202000001_switch_to_subaccount_encryption.sql,sha
|
|
13
13
|
hippius_sdk/db/setup_database.sh,sha256=STp03qxkp2RmIVr6YZIcvQQm-_LLUOb6Jobh-52HWmg,3115
|
14
14
|
hippius_sdk/db_utils.py,sha256=-x0rbN0as7Tn3PJPZBYCgreZe52FLH40ppA1TLxsg90,1851
|
15
15
|
hippius_sdk/errors.py,sha256=LScJJmawVAx7aRzqqQguYSkf9iazSjEQEBNlD_GXZ6Y,1589
|
16
|
-
hippius_sdk/ipfs.py,sha256=
|
16
|
+
hippius_sdk/ipfs.py,sha256=4g_NxQwmocssKu7b6kZ-ShAsF6fyKuj6IiYGCTNrpis,96918
|
17
17
|
hippius_sdk/ipfs_core.py,sha256=X4yO9M_lSNtqiEJu5R-XX97eWzbL7GrN5MOk56p8pJk,12748
|
18
18
|
hippius_sdk/key_storage.py,sha256=SXFd6aGQw9MDLGX2vSBuAY7rdX-k5EvFm63z7_n-8yQ,8148
|
19
19
|
hippius_sdk/substrate.py,sha256=4a7UIE4UqGcDW7luKTBgSDqfb2OIZusB39G1UiRs_YU,50158
|
20
20
|
hippius_sdk/utils.py,sha256=rJ611yvwKSyiBpYU3w-SuyQxoghMGU-ePuslrPv5H5g,7388
|
21
|
-
hippius-0.2.
|
22
|
-
hippius-0.2.
|
23
|
-
hippius-0.2.
|
24
|
-
hippius-0.2.
|
21
|
+
hippius-0.2.39.dist-info/METADATA,sha256=CbQCM8vIuc9v4rDhLma0swGipTVtQyrl7JI7mAA14dU,30088
|
22
|
+
hippius-0.2.39.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
23
|
+
hippius-0.2.39.dist-info/entry_points.txt,sha256=bFAZjW3vndretf9-8s587jA2ebMVI7puhn_lVs8jPc8,149
|
24
|
+
hippius-0.2.39.dist-info/RECORD,,
|
hippius_sdk/__init__.py
CHANGED
@@ -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.39"
|
30
30
|
__all__ = [
|
31
31
|
"HippiusClient",
|
32
32
|
"IPFSClient",
|
hippius_sdk/client.py
CHANGED
@@ -3,13 +3,13 @@ Main client for the Hippius SDK.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import base64
|
6
|
-
from typing import Any, Callable, Dict, List, Optional
|
6
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
7
7
|
|
8
8
|
import nacl.secret
|
9
9
|
import nacl.utils
|
10
10
|
|
11
11
|
from hippius_sdk.config import get_config_value, get_encryption_key
|
12
|
-
from hippius_sdk.ipfs import IPFSClient, S3PublishResult, S3DownloadResult
|
12
|
+
from hippius_sdk.ipfs import IPFSClient, S3PublishResult, S3PublishPin, S3DownloadResult
|
13
13
|
from hippius_sdk.substrate import SubstrateClient
|
14
14
|
|
15
15
|
|
@@ -525,7 +525,8 @@ class HippiusClient:
|
|
525
525
|
store_node: str = "http://localhost:5001",
|
526
526
|
pin_node: str = "https://store.hippius.network",
|
527
527
|
substrate_url: str = "wss://rpc.hippius.network",
|
528
|
-
|
528
|
+
publish: bool = True,
|
529
|
+
) -> Union[S3PublishResult, S3PublishPin]:
|
529
530
|
"""
|
530
531
|
Publish a file to IPFS and the Hippius marketplace in one operation.
|
531
532
|
|
@@ -541,10 +542,12 @@ class HippiusClient:
|
|
541
542
|
bucket_name: The bucket name for key isolation
|
542
543
|
store_node: IPFS node URL for initial upload (default: local node)
|
543
544
|
pin_node: IPFS node URL for backup pinning (default: remote service)
|
544
|
-
substrate_url: substrate url to use for the storage request
|
545
|
+
substrate_url: substrate url to use for the storage request
|
546
|
+
publish: Whether to publish to blockchain (True) or just upload to IPFS (False)
|
545
547
|
|
546
548
|
Returns:
|
547
|
-
S3PublishResult: Object containing CID, file info, and transaction hash
|
549
|
+
S3PublishResult: Object containing CID, file info, and transaction hash when publish=True
|
550
|
+
S3PublishPin: Object containing CID, subaccount, file_path, pin_node, substrate_url when publish=False
|
548
551
|
|
549
552
|
Raises:
|
550
553
|
HippiusIPFSError: If IPFS operations (add or pin) fail
|
@@ -561,6 +564,7 @@ class HippiusClient:
|
|
561
564
|
store_node,
|
562
565
|
pin_node,
|
563
566
|
substrate_url,
|
567
|
+
publish,
|
564
568
|
)
|
565
569
|
|
566
570
|
async def s3_download(
|
hippius_sdk/ipfs.py
CHANGED
@@ -12,7 +12,7 @@ import shutil
|
|
12
12
|
import tempfile
|
13
13
|
import time
|
14
14
|
import uuid
|
15
|
-
from typing import Any, Callable, Dict, List, Optional
|
15
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
16
16
|
|
17
17
|
import httpx
|
18
18
|
from pydantic import BaseModel
|
@@ -62,6 +62,16 @@ class S3PublishResult(BaseModel):
|
|
62
62
|
tx_hash: str
|
63
63
|
|
64
64
|
|
65
|
+
class S3PublishPin(BaseModel):
|
66
|
+
"""Result model for s3_publish method when publish=False."""
|
67
|
+
|
68
|
+
cid: str
|
69
|
+
subaccount: str
|
70
|
+
file_path: str
|
71
|
+
pin_node: str
|
72
|
+
substrate_url: str
|
73
|
+
|
74
|
+
|
65
75
|
class S3DownloadResult(BaseModel):
|
66
76
|
"""Result model for s3_download method."""
|
67
77
|
|
@@ -1958,7 +1968,8 @@ class IPFSClient:
|
|
1958
1968
|
store_node: str = "http://localhost:5001",
|
1959
1969
|
pin_node: str = "https://store.hippius.network",
|
1960
1970
|
substrate_url: str = "wss://rpc.hippius.network",
|
1961
|
-
|
1971
|
+
publish: bool = True,
|
1972
|
+
) -> Union[S3PublishResult, S3PublishPin]:
|
1962
1973
|
"""
|
1963
1974
|
Publish a file to IPFS and the Hippius marketplace in one operation.
|
1964
1975
|
|
@@ -1980,10 +1991,12 @@ class IPFSClient:
|
|
1980
1991
|
bucket_name: The bucket name for key isolation
|
1981
1992
|
store_node: IPFS node URL for initial upload (default: local node)
|
1982
1993
|
pin_node: IPFS node URL for backup pinning (default: remote service)
|
1983
|
-
substrate_url: the substrate url to connect to for the storage request
|
1994
|
+
substrate_url: the substrate url to connect to for the storage request
|
1995
|
+
publish: Whether to publish to blockchain (True) or just upload to IPFS (False)
|
1984
1996
|
|
1985
1997
|
Returns:
|
1986
|
-
S3PublishResult: Object containing CID, file info, and transaction hash
|
1998
|
+
S3PublishResult: Object containing CID, file info, and transaction hash when publish=True
|
1999
|
+
S3PublishPin: Object containing CID, subaccount, file_path, pin_node, substrate_url when publish=False
|
1987
2000
|
|
1988
2001
|
Raises:
|
1989
2002
|
HippiusIPFSError: If IPFS operations (add or pin) fail
|
@@ -2094,54 +2107,64 @@ class IPFSClient:
|
|
2094
2107
|
f"Failed to pin file to store node {store_node}: {str(e)}"
|
2095
2108
|
)
|
2096
2109
|
|
2097
|
-
#
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2110
|
+
# Conditionally publish to substrate marketplace based on publish flag
|
2111
|
+
if publish:
|
2112
|
+
try:
|
2113
|
+
# Pass the seed phrase directly to avoid password prompts for encrypted config
|
2114
|
+
substrate_client = SubstrateClient(
|
2115
|
+
seed_phrase=seed_phrase, url=substrate_url
|
2116
|
+
)
|
2117
|
+
logger.info(
|
2118
|
+
f"Submitting storage request to substrate for file: {filename}, CID: {cid}"
|
2119
|
+
)
|
2106
2120
|
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2121
|
+
tx_hash = await substrate_client.storage_request(
|
2122
|
+
files=[
|
2123
|
+
FileInput(
|
2124
|
+
file_hash=cid,
|
2125
|
+
file_name=filename,
|
2126
|
+
)
|
2127
|
+
],
|
2128
|
+
miner_ids=[],
|
2129
|
+
seed_phrase=seed_phrase,
|
2130
|
+
)
|
2117
2131
|
|
2118
|
-
|
2132
|
+
logger.debug(f"Substrate call result: {tx_hash}")
|
2119
2133
|
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2134
|
+
# Check if we got a valid transaction hash
|
2135
|
+
if not tx_hash or tx_hash == "0x" or len(tx_hash) < 10:
|
2136
|
+
logger.error(f"Invalid transaction hash received: {tx_hash}")
|
2137
|
+
raise HippiusSubstrateError(
|
2138
|
+
f"Invalid transaction hash received: {tx_hash}. This might indicate insufficient credits or transaction failure."
|
2139
|
+
)
|
2140
|
+
|
2141
|
+
logger.info(
|
2142
|
+
f"Successfully published to substrate with transaction: {tx_hash}"
|
2125
2143
|
)
|
2126
2144
|
|
2127
|
-
|
2128
|
-
f"
|
2145
|
+
except Exception as e:
|
2146
|
+
logger.error(f"Substrate call failed: {str(e)}")
|
2147
|
+
logger.debug(
|
2148
|
+
"Possible causes: insufficient credits, network issues, invalid seed phrase, or substrate node unavailability"
|
2149
|
+
)
|
2150
|
+
raise HippiusSubstrateError(f"Failed to publish to substrate: {str(e)}")
|
2151
|
+
|
2152
|
+
return S3PublishResult(
|
2153
|
+
cid=cid,
|
2154
|
+
file_name=filename,
|
2155
|
+
size_bytes=size_bytes,
|
2156
|
+
encryption_key=encryption_key_used,
|
2157
|
+
tx_hash=tx_hash,
|
2129
2158
|
)
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2159
|
+
else:
|
2160
|
+
# Return S3PublishPin with required information when not publishing
|
2161
|
+
return S3PublishPin(
|
2162
|
+
cid=cid,
|
2163
|
+
subaccount=subaccount_id,
|
2164
|
+
file_path=file_path,
|
2165
|
+
pin_node=pin_node,
|
2166
|
+
substrate_url=substrate_url,
|
2135
2167
|
)
|
2136
|
-
raise HippiusSubstrateError(f"Failed to publish to substrate: {str(e)}")
|
2137
|
-
|
2138
|
-
return S3PublishResult(
|
2139
|
-
cid=cid,
|
2140
|
-
file_name=filename,
|
2141
|
-
size_bytes=size_bytes,
|
2142
|
-
encryption_key=encryption_key_used,
|
2143
|
-
tx_hash=tx_hash,
|
2144
|
-
)
|
2145
2168
|
|
2146
2169
|
async def s3_download(
|
2147
2170
|
self,
|
@@ -2180,7 +2203,7 @@ class IPFSClient:
|
|
2180
2203
|
"""
|
2181
2204
|
start_time = time.time()
|
2182
2205
|
|
2183
|
-
# Download the file directly from the specified download_node
|
2206
|
+
# Download the file directly into memory from the specified download_node
|
2184
2207
|
try:
|
2185
2208
|
# Create parent directories if they don't exist
|
2186
2209
|
os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
|
@@ -2188,41 +2211,29 @@ class IPFSClient:
|
|
2188
2211
|
download_client = AsyncIPFSClient(api_url=download_node)
|
2189
2212
|
|
2190
2213
|
download_url = f"{download_node.rstrip('/')}/api/v0/cat?arg={cid}"
|
2214
|
+
|
2215
|
+
# Download file into memory
|
2216
|
+
file_data = bytearray()
|
2191
2217
|
async with download_client.client.stream("POST", download_url) as response:
|
2192
2218
|
response.raise_for_status()
|
2219
|
+
async for chunk in response.aiter_bytes(chunk_size=8192):
|
2220
|
+
file_data.extend(chunk)
|
2193
2221
|
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
logger.info(f"File downloaded from {download_node} with CID: {cid}")
|
2222
|
+
# Convert to bytes for consistency
|
2223
|
+
file_data = bytes(file_data)
|
2224
|
+
logger.info(f"File downloaded from {download_node} with CID: {cid} ({len(file_data)} bytes)")
|
2199
2225
|
|
2200
2226
|
except Exception as e:
|
2201
2227
|
raise HippiusIPFSError(
|
2202
2228
|
f"Failed to download file from {download_node}: {str(e)}"
|
2203
2229
|
)
|
2204
2230
|
|
2205
|
-
# Get file info after download
|
2206
|
-
size_bytes = os.path.getsize(output_path)
|
2207
|
-
elapsed_time = time.time() - start_time
|
2208
|
-
|
2209
2231
|
# Attempt automatic decryption if requested
|
2210
2232
|
decrypted = False
|
2211
2233
|
encryption_key_used = None
|
2234
|
+
final_data = file_data # This will hold either encrypted or decrypted data
|
2212
2235
|
|
2213
2236
|
if auto_decrypt:
|
2214
|
-
# Check if key storage is enabled and available
|
2215
|
-
try:
|
2216
|
-
key_storage_available = is_key_storage_enabled()
|
2217
|
-
logger.debug(f"Key storage enabled: {key_storage_available}")
|
2218
|
-
except ImportError:
|
2219
|
-
logger.debug("Key storage module not available")
|
2220
|
-
key_storage_available = False
|
2221
|
-
|
2222
|
-
# Read the downloaded file content
|
2223
|
-
with open(output_path, "rb") as f:
|
2224
|
-
file_data = f.read()
|
2225
|
-
|
2226
2237
|
# Check if file is empty - this indicates a problem
|
2227
2238
|
if len(file_data) == 0:
|
2228
2239
|
logger.error(f"Downloaded file is empty (0 bytes) for CID: {cid}")
|
@@ -2240,6 +2251,14 @@ class IPFSClient:
|
|
2240
2251
|
decrypted = False
|
2241
2252
|
encryption_key_used = None
|
2242
2253
|
else:
|
2254
|
+
# Check if key storage is enabled and available
|
2255
|
+
try:
|
2256
|
+
key_storage_available = is_key_storage_enabled()
|
2257
|
+
logger.debug(f"Key storage enabled: {key_storage_available}")
|
2258
|
+
except ImportError:
|
2259
|
+
logger.debug("Key storage module not available")
|
2260
|
+
key_storage_available = False
|
2261
|
+
|
2243
2262
|
# File has content, attempt decryption if requested
|
2244
2263
|
decryption_attempted = False
|
2245
2264
|
decryption_successful = False
|
@@ -2269,17 +2288,10 @@ class IPFSClient:
|
|
2269
2288
|
existing_key_b64
|
2270
2289
|
)
|
2271
2290
|
box = nacl.secret.SecretBox(encryption_key_bytes)
|
2272
|
-
|
2273
|
-
|
2274
|
-
# Write the decrypted data back to the file
|
2275
|
-
with open(output_path, "wb") as f:
|
2276
|
-
f.write(decrypted_data)
|
2291
|
+
final_data = box.decrypt(file_data)
|
2277
2292
|
|
2278
2293
|
decryption_successful = True
|
2279
2294
|
decrypted = True
|
2280
|
-
size_bytes = len(
|
2281
|
-
decrypted_data
|
2282
|
-
) # Update size to decrypted size
|
2283
2295
|
logger.info(
|
2284
2296
|
"Successfully decrypted file using stored key"
|
2285
2297
|
)
|
@@ -2303,17 +2315,10 @@ class IPFSClient:
|
|
2303
2315
|
decryption_attempted = True
|
2304
2316
|
|
2305
2317
|
try:
|
2306
|
-
|
2307
|
-
|
2308
|
-
# Write the decrypted data back to the file
|
2309
|
-
with open(output_path, "wb") as f:
|
2310
|
-
f.write(decrypted_data)
|
2318
|
+
final_data = self.decrypt_data(file_data)
|
2311
2319
|
|
2312
2320
|
decryption_successful = True
|
2313
2321
|
decrypted = True
|
2314
|
-
size_bytes = len(
|
2315
|
-
decrypted_data
|
2316
|
-
) # Update size to decrypted size
|
2317
2322
|
|
2318
2323
|
# Store the encryption key for the result
|
2319
2324
|
encryption_key_used = (
|
@@ -2338,6 +2343,14 @@ class IPFSClient:
|
|
2338
2343
|
elif not decryption_attempted:
|
2339
2344
|
logger.debug("No decryption attempted - no keys available")
|
2340
2345
|
|
2346
|
+
# Write the final data (encrypted or decrypted) to disk once
|
2347
|
+
with open(output_path, "wb") as f:
|
2348
|
+
f.write(final_data)
|
2349
|
+
|
2350
|
+
# Get final file info
|
2351
|
+
size_bytes = len(final_data)
|
2352
|
+
elapsed_time = time.time() - start_time
|
2353
|
+
|
2341
2354
|
return S3DownloadResult(
|
2342
2355
|
cid=cid,
|
2343
2356
|
output_path=output_path,
|
File without changes
|
File without changes
|