hippius 0.2.20__py3-none-any.whl → 0.2.22__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hippius
3
- Version: 0.2.20
3
+ Version: 0.2.22
4
4
  Summary: Python SDK and CLI for Hippius blockchain storage
5
5
  Home-page: https://github.com/thenervelab/hippius-sdk
6
6
  Author: Dubs
@@ -1,10 +1,10 @@
1
- hippius_sdk/__init__.py,sha256=9rPlh9Ob5xHhR9owW4IxihHaanA0vxuMrDidpW5l0Fw,1474
1
+ hippius_sdk/__init__.py,sha256=iVksJT4wiSP49OCa5MhECb_uiiL4zUJg6vGkdhd83J8,1474
2
2
  hippius_sdk/cli.py,sha256=aqKOYSBSWt7UhcpFt7wf9yIPJ3bznpsJ6ehOnuZ4usI,18235
3
3
  hippius_sdk/cli_assets.py,sha256=V3MX63QTiex6mCp0VDXQJ7cagm5v1s4xtsu8c1O4G_k,371
4
4
  hippius_sdk/cli_handlers.py,sha256=TQNE9os87gRzRKLEO-SIwhFnBtEFMiaSESv-Bu7omfo,128909
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=k8K3__zDtWJhCbHPAPYu9FopSNXsrw1HpVAX6fV7pnI,21462
7
+ hippius_sdk/client.py,sha256=Hj87gu5kapNM0V0-EgwJBsuA63HTsVHFGr2VnmwFH6I,22298
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
@@ -12,12 +12,12 @@ hippius_sdk/db/migrations/20241201000001_create_key_storage_tables.sql,sha256=mi
12
12
  hippius_sdk/db/setup_database.sh,sha256=bDeIiTnMuX0AYCdefAfEI1CyXho6A6kLzufsDZFSXpE,3118
13
13
  hippius_sdk/db_utils.py,sha256=-x0rbN0as7Tn3PJPZBYCgreZe52FLH40ppA1TLxsg90,1851
14
14
  hippius_sdk/errors.py,sha256=LScJJmawVAx7aRzqqQguYSkf9iazSjEQEBNlD_GXZ6Y,1589
15
- hippius_sdk/ipfs.py,sha256=Bp-f4QjrPeLKy61SxNsmB_YWvVjcYVBJlTt4NN6mGWo,90907
15
+ hippius_sdk/ipfs.py,sha256=0ev7uRubsVDkr0003NVk4b9PnKAFSWVl4U9Yubs8kYk,93900
16
16
  hippius_sdk/ipfs_core.py,sha256=eOOgLoyP9mvwndnCjldnTc7z94ImYCXY3nm7JU3e_Mo,12676
17
- hippius_sdk/key_storage.py,sha256=-f4pEUvkczY_yw3lYJ_kM2iDDOAtKOgrexWxVgIo78w,9486
18
- hippius_sdk/substrate.py,sha256=AqfQNl5Qv_s6roOESSdwleX0-VGyu5sh3m5-dYZp5ek,49079
17
+ hippius_sdk/key_storage.py,sha256=oxfRRQXu8XVncUjhKJJ8rsc81JAkaj9MqZEwQa96idc,9474
18
+ hippius_sdk/substrate.py,sha256=-lIavQkfE6Kw2KzllH9IMgNkzl2d6vEmU3RmwKNJQvc,48093
19
19
  hippius_sdk/utils.py,sha256=rJ611yvwKSyiBpYU3w-SuyQxoghMGU-ePuslrPv5H5g,7388
20
- hippius-0.2.20.dist-info/METADATA,sha256=-mfl3cVtxZhaYbQvq-yt2aR96T1szZxnCb_R3Xbhx5I,30088
21
- hippius-0.2.20.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
22
- hippius-0.2.20.dist-info/entry_points.txt,sha256=bFAZjW3vndretf9-8s587jA2ebMVI7puhn_lVs8jPc8,149
23
- hippius-0.2.20.dist-info/RECORD,,
20
+ hippius-0.2.22.dist-info/METADATA,sha256=bBkLq84px0hNLf4JXZKi1tGC1YrfN8dU_ZPzmDdHTUk,30088
21
+ hippius-0.2.22.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
22
+ hippius-0.2.22.dist-info/entry_points.txt,sha256=bFAZjW3vndretf9-8s587jA2ebMVI7puhn_lVs8jPc8,149
23
+ hippius-0.2.22.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.20"
29
+ __version__ = "0.2.22"
30
30
  __all__ = [
31
31
  "HippiusClient",
32
32
  "IPFSClient",
hippius_sdk/client.py CHANGED
@@ -512,15 +512,26 @@ class HippiusClient:
512
512
  )
513
513
 
514
514
  async def s3_publish(
515
- self, file_path: str, encrypt: bool, seed_phrase: str
515
+ self,
516
+ file_path: str,
517
+ encrypt: bool,
518
+ seed_phrase: str,
519
+ store_node: str = "http://localhost:5001",
520
+ pin_node: str = "https://store.hippius.network",
516
521
  ) -> S3PublishResult:
517
522
  """
518
523
  Publish a file to IPFS and the Hippius marketplace in one operation.
519
524
 
525
+ Uses a two-node architecture for optimal performance:
526
+ 1. Uploads to store_node (local) for immediate availability
527
+ 2. Pins to pin_node (remote) for persistence and backup
528
+
520
529
  Args:
521
530
  file_path: Path to the file to publish
522
531
  encrypt: Whether to encrypt the file before uploading
523
532
  seed_phrase: Seed phrase for blockchain transaction signing
533
+ store_node: IPFS node URL for initial upload (default: local node)
534
+ pin_node: IPFS node URL for backup pinning (default: remote service)
524
535
 
525
536
  Returns:
526
537
  S3PublishResult: Object containing CID, file info, and transaction hash
@@ -531,16 +542,24 @@ class HippiusClient:
531
542
  FileNotFoundError: If the file doesn't exist
532
543
  ValueError: If encryption is requested but not available
533
544
  """
534
- return await self.ipfs_client.s3_publish(file_path, encrypt, seed_phrase)
545
+ return await self.ipfs_client.s3_publish(
546
+ file_path, encrypt, seed_phrase, store_node, pin_node
547
+ )
535
548
 
536
549
  async def s3_download(
537
- self, cid: str, output_path: str, seed_phrase: str, auto_decrypt: bool = True
550
+ self,
551
+ cid: str,
552
+ output_path: str,
553
+ seed_phrase: str,
554
+ auto_decrypt: bool = True,
555
+ download_node: str = "http://localhost:5001",
538
556
  ) -> S3DownloadResult:
539
557
  """
540
558
  Download a file from IPFS with automatic decryption.
541
559
 
542
- This method automatically manages decryption keys per seed phrase:
543
- - Downloads the file from IPFS
560
+ This method uses the download_node for immediate availability and automatically
561
+ manages decryption keys per seed phrase:
562
+ - Downloads the file from the specified download_node (local by default)
544
563
  - If auto_decrypt=True, attempts to decrypt using stored keys for the seed phrase
545
564
  - Falls back to client encryption key if key storage is not available
546
565
  - Returns the file in decrypted form if decryption succeeds
@@ -550,6 +569,7 @@ class HippiusClient:
550
569
  output_path: Path where the downloaded file will be saved
551
570
  seed_phrase: Seed phrase to use for retrieving decryption keys
552
571
  auto_decrypt: Whether to attempt automatic decryption (default: True)
572
+ download_node: IPFS node URL for download (default: local node)
553
573
 
554
574
  Returns:
555
575
  S3DownloadResult: Object containing download info and decryption status
@@ -559,4 +579,6 @@ class HippiusClient:
559
579
  FileNotFoundError: If the output directory doesn't exist
560
580
  ValueError: If decryption fails
561
581
  """
562
- return await self.ipfs_client.s3_download(cid, output_path, seed_phrase, auto_decrypt)
582
+ return await self.ipfs_client.s3_download(
583
+ cid, output_path, seed_phrase, auto_decrypt, download_node
584
+ )
hippius_sdk/ipfs.py CHANGED
@@ -13,17 +13,18 @@ import tempfile
13
13
  import time
14
14
  import uuid
15
15
  from typing import Any, Callable, Dict, List, Optional
16
- from hippius_sdk.key_storage import (
17
- generate_and_store_key_for_seed,
18
- get_key_for_seed,
19
- is_key_storage_enabled,
20
- )
16
+
21
17
  import httpx
22
18
  from pydantic import BaseModel
23
19
 
24
20
  from hippius_sdk.config import get_config_value, get_encryption_key
25
21
  from hippius_sdk.errors import HippiusIPFSError, HippiusSubstrateError
26
22
  from hippius_sdk.ipfs_core import AsyncIPFSClient
23
+ from hippius_sdk.key_storage import (
24
+ generate_and_store_key_for_seed,
25
+ get_key_for_seed,
26
+ is_key_storage_enabled,
27
+ )
27
28
  from hippius_sdk.substrate import FileInput, SubstrateClient
28
29
  from hippius_sdk.utils import format_cid, format_size
29
30
 
@@ -1805,9 +1806,6 @@ class IPFSClient:
1805
1806
  """
1806
1807
  print(f"Starting deletion process for metadata CID: {metadata_cid}")
1807
1808
 
1808
- # Try to download and process metadata file and chunks
1809
- ipfs_failure = False
1810
- metadata_error = False
1811
1809
  chunks = []
1812
1810
 
1813
1811
  try:
@@ -1929,11 +1927,21 @@ class IPFSClient:
1929
1927
  return True
1930
1928
 
1931
1929
  async def s3_publish(
1932
- self, file_path: str, encrypt: bool, seed_phrase: str
1930
+ self,
1931
+ file_path: str,
1932
+ encrypt: bool,
1933
+ seed_phrase: str,
1934
+ store_node: str = "http://localhost:5001",
1935
+ pin_node: str = "https://store.hippius.network",
1933
1936
  ) -> S3PublishResult:
1934
1937
  """
1935
1938
  Publish a file to IPFS and the Hippius marketplace in one operation.
1936
1939
 
1940
+ This method uses a two-node architecture for optimal performance:
1941
+ 1. Uploads to store_node (local) for immediate availability
1942
+ 2. Pins to pin_node (remote) for persistence and backup
1943
+ 3. Publishes to substrate marketplace
1944
+
1937
1945
  This method automatically manages encryption keys per seed phrase:
1938
1946
  - If encrypt=True, it will get or generate an encryption key for the seed phrase
1939
1947
  - Keys are stored in PostgreSQL and versioned (never deleted)
@@ -1943,6 +1951,8 @@ class IPFSClient:
1943
1951
  file_path: Path to the file to publish
1944
1952
  encrypt: Whether to encrypt the file before uploading
1945
1953
  seed_phrase: Seed phrase for blockchain transaction signing
1954
+ store_node: IPFS node URL for initial upload (default: local node)
1955
+ pin_node: IPFS node URL for backup pinning (default: remote service)
1946
1956
 
1947
1957
  Returns:
1948
1958
  S3PublishResult: Object containing CID, file info, and transaction hash
@@ -2026,18 +2036,26 @@ class IPFSClient:
2026
2036
  else None
2027
2037
  )
2028
2038
 
2029
- # Add file to IPFS
2039
+ # Step 1: Upload to store_node (local) for immediate availability
2030
2040
  try:
2031
- result = await self.client.add_file(file_path)
2041
+ store_client = AsyncIPFSClient(api_url=store_node)
2042
+ result = await store_client.add_file(file_path)
2032
2043
  cid = result["Hash"]
2044
+ logger.info(f"File uploaded to store node {store_node} with CID: {cid}")
2033
2045
  except Exception as e:
2034
- raise HippiusIPFSError(f"Failed to add file to IPFS: {str(e)}")
2046
+ raise HippiusIPFSError(
2047
+ f"Failed to upload file to store node {store_node}: {str(e)}"
2048
+ )
2035
2049
 
2036
- # Pin the file to IPFS
2050
+ # Step 2: Pin to pin_node (remote) for persistence and backup
2037
2051
  try:
2038
- pin_result = await self.client.pin(cid)
2052
+ pin_client = AsyncIPFSClient(api_url=pin_node)
2053
+ await pin_client.pin(cid)
2054
+ logger.info(f"File pinned to backup node {pin_node}")
2039
2055
  except Exception as e:
2040
- raise HippiusIPFSError(f"Failed to pin file to IPFS: {str(e)}")
2056
+ raise HippiusIPFSError(
2057
+ f"Failed to pin file to store node {store_node}: {str(e)}"
2058
+ )
2041
2059
 
2042
2060
  # Publish to substrate marketplace
2043
2061
  try:
@@ -2087,13 +2105,19 @@ class IPFSClient:
2087
2105
  )
2088
2106
 
2089
2107
  async def s3_download(
2090
- self, cid: str, output_path: str, seed_phrase: str, auto_decrypt: bool = True
2108
+ self,
2109
+ cid: str,
2110
+ output_path: str,
2111
+ seed_phrase: str,
2112
+ auto_decrypt: bool = True,
2113
+ download_node: str = "http://localhost:5001",
2091
2114
  ) -> S3DownloadResult:
2092
2115
  """
2093
2116
  Download a file from IPFS with automatic decryption.
2094
2117
 
2095
- This method automatically manages decryption keys per seed phrase:
2096
- - Downloads the file from IPFS
2118
+ This method uses the download_node for immediate availability and automatically
2119
+ manages decryption keys per seed phrase:
2120
+ - Downloads the file from the specified download_node (local by default)
2097
2121
  - If auto_decrypt=True, attempts to decrypt using stored keys for the seed phrase
2098
2122
  - Falls back to client encryption key if key storage is not available
2099
2123
  - Returns the file in decrypted form if decryption succeeds
@@ -2103,6 +2127,7 @@ class IPFSClient:
2103
2127
  output_path: Path where the downloaded file will be saved
2104
2128
  seed_phrase: Seed phrase to use for retrieving decryption keys
2105
2129
  auto_decrypt: Whether to attempt automatic decryption (default: True)
2130
+ download_node: IPFS node URL for download (default: local node)
2106
2131
 
2107
2132
  Returns:
2108
2133
  S3DownloadResult: Object containing download info and decryption status
@@ -2114,24 +2139,27 @@ class IPFSClient:
2114
2139
  """
2115
2140
  start_time = time.time()
2116
2141
 
2117
- # Download the file first using the existing download_file method
2142
+ # Download the file directly from the specified download_node
2118
2143
  try:
2119
2144
  # Create parent directories if they don't exist
2120
2145
  os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
2121
2146
 
2122
- # Download without decryption first
2123
- download_result = await self.download_file(
2124
- cid=cid,
2125
- output_path=output_path,
2126
- skip_directory_check=False,
2127
- seed_phrase=seed_phrase,
2128
- )
2147
+ download_client = AsyncIPFSClient(api_url=download_node)
2148
+
2149
+ download_url = f"{download_node.rstrip('/')}/api/v0/cat?arg={cid}"
2150
+ async with download_client.client.stream("POST", download_url) as response:
2151
+ response.raise_for_status()
2152
+
2153
+ with open(output_path, "wb") as f:
2154
+ async for chunk in response.aiter_bytes(chunk_size=8192):
2155
+ f.write(chunk)
2129
2156
 
2130
- if not download_result.get("success", False):
2131
- raise HippiusIPFSError("Download failed")
2157
+ logger.info(f"File downloaded from {download_node} with CID: {cid}")
2132
2158
 
2133
2159
  except Exception as e:
2134
- raise HippiusIPFSError(f"Failed to download file from IPFS: {str(e)}")
2160
+ raise HippiusIPFSError(
2161
+ f"Failed to download file from {download_node}: {str(e)}"
2162
+ )
2135
2163
 
2136
2164
  # Get file info after download
2137
2165
  size_bytes = os.path.getsize(output_path)
@@ -2154,77 +2182,113 @@ class IPFSClient:
2154
2182
  with open(output_path, "rb") as f:
2155
2183
  file_data = f.read()
2156
2184
 
2157
- decryption_attempted = False
2158
- decryption_successful = False
2159
-
2160
- if key_storage_available:
2161
- # Try to get the encryption key for this seed phrase
2162
- try:
2163
- existing_key_b64 = await get_key_for_seed(seed_phrase)
2185
+ # Check if file is empty - this indicates a problem
2186
+ if len(file_data) == 0:
2187
+ logger.error(f"Downloaded file is empty (0 bytes) for CID: {cid}")
2188
+ raise HippiusIPFSError(
2189
+ f"File not available: Downloaded 0 bytes for CID {cid}. "
2190
+ f"File may not exist on download node {download_node}. "
2191
+ f"Download URL: {download_url}"
2192
+ )
2193
+ elif (
2194
+ len(file_data) < 40
2195
+ ): # PyNaCl encrypted data is at least 40 bytes (24-byte nonce + 16-byte auth tag + data)
2196
+ logger.info(
2197
+ f"File too small to be encrypted ({len(file_data)} bytes), treating as plaintext"
2198
+ )
2199
+ decrypted = False
2200
+ encryption_key_used = None
2201
+ else:
2202
+ # File has content, attempt decryption if requested
2203
+ decryption_attempted = False
2204
+ decryption_successful = False
2164
2205
 
2165
- if existing_key_b64:
2166
- logger.debug("Found encryption key for seed phrase, attempting decryption")
2167
- decryption_attempted = True
2168
- encryption_key_used = existing_key_b64
2206
+ if key_storage_available:
2207
+ # Try to get the encryption key for this seed phrase
2208
+ try:
2209
+ existing_key_b64 = await get_key_for_seed(seed_phrase)
2169
2210
 
2170
- # Attempt decryption with the stored key
2171
- try:
2172
- import nacl.secret
2211
+ if existing_key_b64:
2212
+ logger.debug(
2213
+ "Found encryption key for seed phrase, attempting decryption"
2214
+ )
2215
+ decryption_attempted = True
2216
+ encryption_key_used = existing_key_b64
2173
2217
 
2174
- encryption_key_bytes = base64.b64decode(existing_key_b64)
2175
- box = nacl.secret.SecretBox(encryption_key_bytes)
2176
- decrypted_data = box.decrypt(file_data)
2218
+ # Attempt decryption with the stored key
2219
+ try:
2220
+ import nacl.secret
2177
2221
 
2178
- # Write the decrypted data back to the file
2179
- with open(output_path, "wb") as f:
2180
- f.write(decrypted_data)
2222
+ encryption_key_bytes = base64.b64decode(
2223
+ existing_key_b64
2224
+ )
2225
+ box = nacl.secret.SecretBox(encryption_key_bytes)
2226
+ decrypted_data = box.decrypt(file_data)
2227
+
2228
+ # Write the decrypted data back to the file
2229
+ with open(output_path, "wb") as f:
2230
+ f.write(decrypted_data)
2231
+
2232
+ decryption_successful = True
2233
+ decrypted = True
2234
+ size_bytes = len(
2235
+ decrypted_data
2236
+ ) # Update size to decrypted size
2237
+ logger.info(
2238
+ "Successfully decrypted file using stored key"
2239
+ )
2181
2240
 
2182
- decryption_successful = True
2183
- decrypted = True
2184
- size_bytes = len(decrypted_data) # Update size to decrypted size
2185
- logger.info("Successfully decrypted file using stored key")
2241
+ except Exception as decrypt_error:
2242
+ logger.debug(
2243
+ f"Decryption failed with stored key: {decrypt_error}"
2244
+ )
2245
+ # Continue to try fallback decryption
2246
+ else:
2247
+ logger.debug("No encryption key found for seed phrase")
2186
2248
 
2187
- except Exception as decrypt_error:
2188
- logger.debug(f"Decryption failed with stored key: {decrypt_error}")
2189
- # Continue to try fallback decryption
2190
- else:
2191
- logger.debug("No encryption key found for seed phrase")
2249
+ except Exception as e:
2250
+ logger.debug(f"Error retrieving key from storage: {e}")
2192
2251
 
2193
- except Exception as e:
2194
- logger.debug(f"Error retrieving key from storage: {e}")
2252
+ # If key storage decryption failed or wasn't available, try client encryption key
2253
+ if not decryption_successful and self.encryption_available:
2254
+ logger.debug("Attempting decryption with client encryption key")
2255
+ decryption_attempted = True
2195
2256
 
2196
- # If key storage decryption failed or wasn't available, try client encryption key
2197
- if not decryption_successful and self.encryption_available:
2198
- logger.debug("Attempting decryption with client encryption key")
2199
- decryption_attempted = True
2257
+ try:
2258
+ decrypted_data = self.decrypt_data(file_data)
2200
2259
 
2201
- try:
2202
- decrypted_data = self.decrypt_data(file_data)
2203
-
2204
- # Write the decrypted data back to the file
2205
- with open(output_path, "wb") as f:
2206
- f.write(decrypted_data)
2207
-
2208
- decryption_successful = True
2209
- decrypted = True
2210
- size_bytes = len(decrypted_data) # Update size to decrypted size
2211
-
2212
- # Store the encryption key for the result
2213
- encryption_key_used = (
2214
- base64.b64encode(self.encryption_key).decode("utf-8")
2215
- if self.encryption_key
2216
- else None
2217
- )
2218
- logger.info("Successfully decrypted file using client encryption key")
2260
+ # Write the decrypted data back to the file
2261
+ with open(output_path, "wb") as f:
2262
+ f.write(decrypted_data)
2263
+
2264
+ decryption_successful = True
2265
+ decrypted = True
2266
+ size_bytes = len(
2267
+ decrypted_data
2268
+ ) # Update size to decrypted size
2269
+
2270
+ # Store the encryption key for the result
2271
+ encryption_key_used = (
2272
+ base64.b64encode(self.encryption_key).decode("utf-8")
2273
+ if self.encryption_key
2274
+ else None
2275
+ )
2276
+ logger.info(
2277
+ "Successfully decrypted file using client encryption key"
2278
+ )
2219
2279
 
2220
- except Exception as decrypt_error:
2221
- logger.debug(f"Decryption failed with client key: {decrypt_error}")
2280
+ except Exception as decrypt_error:
2281
+ logger.debug(
2282
+ f"Decryption failed with client key: {decrypt_error}"
2283
+ )
2222
2284
 
2223
- # Log final decryption status
2224
- if decryption_attempted and not decryption_successful:
2225
- logger.info("File may not be encrypted or decryption keys don't match")
2226
- elif not decryption_attempted:
2227
- logger.debug("No decryption attempted - no keys available")
2285
+ # Log final decryption status
2286
+ if decryption_attempted and not decryption_successful:
2287
+ logger.info(
2288
+ "File may not be encrypted or decryption keys don't match"
2289
+ )
2290
+ elif not decryption_attempted:
2291
+ logger.debug("No decryption attempted - no keys available")
2228
2292
 
2229
2293
  return S3DownloadResult(
2230
2294
  cid=cid,
@@ -234,7 +234,7 @@ _default_storage = None
234
234
  def is_key_storage_enabled() -> bool:
235
235
  """
236
236
  Check if key storage is enabled and available.
237
-
237
+
238
238
  Returns True if:
239
239
  1. Explicitly enabled in config, OR
240
240
  2. asyncpg is available (key_storage extra installed) AND not explicitly disabled
@@ -243,11 +243,11 @@ def is_key_storage_enabled() -> bool:
243
243
  config_value = get_config_value("key_storage", "enabled", None)
244
244
  if config_value is False:
245
245
  return False
246
-
246
+
247
247
  # If explicitly enabled, return True
248
248
  if config_value is True:
249
249
  return True
250
-
250
+
251
251
  # If not set in config, auto-detect based on asyncpg availability
252
252
  # This allows users who install [key_storage] extra to use it without manual config
253
253
  return ASYNCPG_AVAILABLE
hippius_sdk/substrate.py CHANGED
@@ -1223,29 +1223,6 @@ class SubstrateClient:
1223
1223
  Returns:
1224
1224
  str: Transaction hash or status message
1225
1225
  """
1226
- # First check if this CID exists in the user's storage requests
1227
- try:
1228
- cid_exists = await self.check_storage_request_exists(cid)
1229
- if not cid_exists:
1230
- raise HippiusAlreadyDeletedError(
1231
- f"CID {cid} is not found in storage requests - may already be deleted"
1232
- )
1233
- except Exception as e:
1234
- if not isinstance(e, HippiusAlreadyDeletedError):
1235
- # If there was an error checking, but not our custom exception, wrap it
1236
- raise HippiusSubstrateConnectionError(
1237
- f"Error checking if CID exists: {str(e)}"
1238
- )
1239
- else:
1240
- # Re-raise our custom exception
1241
- raise
1242
-
1243
- # Continue with cancellation if it exists
1244
- if not self._ensure_keypair(seed_phrase):
1245
- raise HippiusSubstrateAuthError(
1246
- "Valid seed phrase must be provided or available in config"
1247
- )
1248
-
1249
1226
  # Initialize Substrate connection with seed phrase if needed
1250
1227
  if not self._substrate:
1251
1228
  self.connect(seed_phrase)