hippius 0.2.2__tar.gz → 0.2.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hippius
3
- Version: 0.2.2
3
+ Version: 0.2.4
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
@@ -24,6 +24,7 @@ Requires-Dist: pynacl (>=1.5.0,<2.0.0)
24
24
  Requires-Dist: pyperclip (>=1.8.2,<2.0.0) ; extra == "clipboard"
25
25
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
26
26
  Requires-Dist: requests (>=2.28.1,<3.0.0)
27
+ Requires-Dist: rich (>=14.0.0,<15.0.0)
27
28
  Requires-Dist: substrate-interface (>=1.4.2,<2.0.0)
28
29
  Requires-Dist: zfec (>=1.5.3,<2.0.0)
29
30
  Project-URL: Documentation, https://github.com/thenervelab/hippius-sdk/docs
@@ -43,6 +44,7 @@ A Python SDK and CLI for interacting with Hippius blockchain storage, designed s
43
44
  - Substrate blockchain integration for decentralized storage references
44
45
  - End-to-end encryption for secure file storage and retrieval
45
46
  - Built-in CLI tools for encryption key generation
47
+ - Asynchronous API for efficient I/O operations
46
48
 
47
49
  ## Installation
48
50
 
@@ -60,6 +62,7 @@ poetry add hippius -E clipboard
60
62
  ## Quick Start
61
63
 
62
64
  ```python
65
+ import asyncio
63
66
  from hippius_sdk import HippiusClient
64
67
 
65
68
  # Initialize the client with default connections to Hippius network
@@ -67,45 +70,50 @@ client = HippiusClient()
67
70
 
68
71
  # Or specify custom endpoints
69
72
  client = HippiusClient(
70
- ipfs_gateway="https://ipfs.io", # For downloads (default)
73
+ ipfs_gateway="https://get.hippius.network", # For downloads (default)
71
74
  ipfs_api_url="https://store.hippius.network", # For uploads (default)
72
75
  )
73
76
 
74
- # Upload a file to IPFS
75
- result = client.upload_file("path/to/your/model.pt")
76
- print(f"File uploaded with CID: {result['cid']}")
77
- print(f"File size: {result['size_formatted']}")
78
-
79
- # Download a file from IPFS
80
- dl_result = client.download_file(result['cid'], "path/to/save/model.pt")
81
- print(f"Download successful in {dl_result['elapsed_seconds']} seconds")
82
- print(f"File size: {dl_result['size_formatted']}")
83
-
84
- # Check if a file exists
85
- exists_result = client.exists(result['cid'])
86
- print(f"File exists: {exists_result['exists']}")
87
- print(f"Gateway URL: {exists_result['gateway_url']}")
88
-
89
- # Get file content directly
90
- content_result = client.cat(result['cid'])
91
- if content_result['is_text']:
92
- print(f"Content preview: {content_result['text_preview']}")
93
- else:
94
- print(f"Binary content (hex): {content_result['hex_preview']}")
95
- print(f"Content size: {content_result['size_formatted']}")
96
-
97
- # Pin a file to ensure it stays on the network
98
- pin_result = client.pin(result['cid'])
99
- print(f"Pinning successful: {pin_result['success']}")
100
- print(f"Message: {pin_result['message']}")
101
-
102
- # Format a CID for display
103
- formatted_cid = client.format_cid(result['cid'])
104
- print(f"Formatted CID: {formatted_cid}")
105
-
106
- # Format file size for display
107
- formatted_size = client.format_size(1024 * 1024)
108
- print(f"Formatted size: {formatted_size}") # Output: 1.00 MB
77
+ async def main():
78
+ # Upload a file to IPFS
79
+ result = await client.upload_file("path/to/your/model.pt")
80
+ print(f"File uploaded with CID: {result['cid']}")
81
+ print(f"File size: {result['size_formatted']}")
82
+
83
+ # Download a file from IPFS
84
+ dl_result = await client.download_file(result['cid'], "path/to/save/model.pt")
85
+ print(f"Download successful in {dl_result['elapsed_seconds']} seconds")
86
+ print(f"File size: {dl_result['size_formatted']}")
87
+
88
+ # Check if a file exists
89
+ exists_result = await client.exists(result['cid'])
90
+ print(f"File exists: {exists_result['exists']}")
91
+ print(f"Gateway URL: {exists_result['gateway_url']}")
92
+
93
+ # Get file content directly
94
+ content_result = await client.cat(result['cid'])
95
+ if content_result['is_text']:
96
+ print(f"Content preview: {content_result['text_preview']}")
97
+ else:
98
+ print(f"Binary content (hex): {content_result['hex_preview']}")
99
+ print(f"Content size: {content_result['size_formatted']}")
100
+
101
+ # Pin a file to ensure it stays on the network
102
+ pin_result = await client.pin(result['cid'])
103
+ print(f"Pinning successful: {pin_result['success']}")
104
+ print(f"Message: {pin_result['message']}")
105
+
106
+ # Format a CID for display (non-async utility function)
107
+ formatted_cid = client.format_cid(result['cid'])
108
+ print(f"Formatted CID: {formatted_cid}")
109
+
110
+ # Format file size for display (non-async utility function)
111
+ formatted_size = client.format_size(1024 * 1024)
112
+ print(f"Formatted size: {formatted_size}") # Output: 1.00 MB
113
+
114
+ # Run the async function
115
+ if __name__ == "__main__":
116
+ asyncio.run(main())
109
117
  ```
110
118
 
111
119
  ## Encryption Support
@@ -136,6 +144,7 @@ The SDK can be configured to use encryption in several ways:
136
144
  2. Directly in code:
137
145
  ```python
138
146
  import base64
147
+ import asyncio
139
148
  from hippius_sdk import HippiusClient
140
149
 
141
150
  # Decode the base64 key
@@ -147,9 +156,13 @@ The SDK can be configured to use encryption in several ways:
147
156
  encryption_key=encryption_key
148
157
  )
149
158
 
150
- # Or generate a new key programmatically
151
- encoded_key = client.generate_encryption_key()
152
- print(f"Generated key: {encoded_key}")
159
+ async def main():
160
+ # Generate a new key programmatically (non-async utility method)
161
+ encoded_key = client.generate_encryption_key()
162
+ print(f"Generated key: {encoded_key}")
163
+
164
+ # Run the async function
165
+ asyncio.run(main())
153
166
  ```
154
167
 
155
168
  ### Using Encryption
@@ -157,22 +170,31 @@ The SDK can be configured to use encryption in several ways:
157
170
  Once configured, encryption works transparently:
158
171
 
159
172
  ```python
160
- # Upload with encryption (uses default setting)
161
- result = client.upload_file("sensitive_data.txt")
162
-
163
- # Explicitly enable/disable encryption for a specific operation
164
- encrypted_result = client.upload_file("sensitive_data.txt", encrypt=True)
165
- unencrypted_result = client.upload_file("public_data.txt", encrypt=False)
166
-
167
- # Download and decrypt automatically
168
- dl_result = client.download_file(encrypted_result['cid'], "decrypted_file.txt")
173
+ import asyncio
174
+ from hippius_sdk import HippiusClient
169
175
 
170
- # Explicitly control decryption
171
- decrypted_result = client.download_file(encrypted_result['cid'], "output.txt", decrypt=True)
172
- raw_result = client.download_file(encrypted_result['cid'], "still_encrypted.txt", decrypt=False)
176
+ client = HippiusClient()
173
177
 
174
- # View encrypted content
175
- content = client.cat(encrypted_result['cid'], decrypt=True)
178
+ async def main():
179
+ # Upload with encryption (uses default setting)
180
+ result = await client.upload_file("sensitive_data.txt")
181
+
182
+ # Explicitly enable/disable encryption for a specific operation
183
+ encrypted_result = await client.upload_file("sensitive_data.txt", encrypt=True)
184
+ unencrypted_result = await client.upload_file("public_data.txt", encrypt=False)
185
+
186
+ # Download and decrypt automatically
187
+ dl_result = await client.download_file(encrypted_result['cid'], "decrypted_file.txt")
188
+
189
+ # Explicitly control decryption
190
+ decrypted_result = await client.download_file(encrypted_result['cid'], "output.txt", decrypt=True)
191
+ raw_result = await client.download_file(encrypted_result['cid'], "still_encrypted.txt", decrypt=False)
192
+
193
+ # View encrypted content
194
+ content = await client.cat(encrypted_result['cid'], decrypt=True)
195
+
196
+ # Run the async function
197
+ asyncio.run(main())
176
198
  ```
177
199
 
178
200
  ## Erasure Coding
@@ -189,37 +211,42 @@ Hippius SDK supports Reed-Solomon erasure coding for reliable and resilient file
189
211
  ### Using Erasure Coding
190
212
 
191
213
  ```python
214
+ import asyncio
192
215
  from hippius_sdk import HippiusClient
193
216
 
194
217
  client = HippiusClient()
195
218
 
196
- # Erasure code a file with default parameters (k=3, m=5)
197
- result = client.erasure_code_file("large_file.mp4")
198
- metadata_cid = result["metadata_cid"]
199
-
200
- # Use custom parameters for more redundancy
201
- result = client.erasure_code_file(
202
- file_path="important_data.zip",
203
- k=4, # Need 4 chunks to reconstruct
204
- m=10, # Create 10 chunks total (6 redundant)
205
- chunk_size=2097152, # 2MB chunks
206
- encrypt=True # Encrypt before splitting
207
- )
208
-
209
- # Store erasure-coded file in Hippius marketplace
210
- result = client.store_erasure_coded_file(
211
- file_path="critical_backup.tar",
212
- k=3,
213
- m=5,
214
- encrypt=True,
215
- miner_ids=["miner1", "miner2", "miner3"]
216
- )
217
-
218
- # Reconstruct a file from its metadata
219
- reconstructed_path = client.reconstruct_from_erasure_code(
220
- metadata_cid=metadata_cid,
221
- output_file="reconstructed_file.mp4"
222
- )
219
+ async def main():
220
+ # Erasure code a file with default parameters (k=3, m=5)
221
+ result = await client.erasure_code_file("large_file.mp4")
222
+ metadata_cid = result["metadata_cid"]
223
+
224
+ # Use custom parameters for more redundancy
225
+ result = await client.erasure_code_file(
226
+ file_path="important_data.zip",
227
+ k=4, # Need 4 chunks to reconstruct
228
+ m=10, # Create 10 chunks total (6 redundant)
229
+ chunk_size=2097152, # 2MB chunks
230
+ encrypt=True # Encrypt before splitting
231
+ )
232
+
233
+ # Store erasure-coded file in Hippius marketplace
234
+ result = await client.store_erasure_coded_file(
235
+ file_path="critical_backup.tar",
236
+ k=3,
237
+ m=5,
238
+ encrypt=True,
239
+ miner_ids=["miner1", "miner2", "miner3"]
240
+ )
241
+
242
+ # Reconstruct a file from its metadata
243
+ reconstructed_path = await client.reconstruct_from_erasure_code(
244
+ metadata_cid=metadata_cid,
245
+ output_file="reconstructed_file.mp4"
246
+ )
247
+
248
+ # Run the async function
249
+ asyncio.run(main())
223
250
  ```
224
251
 
225
252
  ### When to Use Erasure Coding
@@ -428,7 +455,7 @@ The Hippius SDK includes a powerful command-line interface (CLI) that provides a
428
455
  hippius --help
429
456
 
430
457
  # Set global options
431
- hippius --gateway https://ipfs.io --api-url https://store.hippius.network --verbose
458
+ hippius --gateway https://get.hippius.network --api-url https://store.hippius.network --verbose
432
459
  ```
433
460
 
434
461
  ### IPFS Operations
@@ -520,7 +547,7 @@ The `ec-files` command has been optimized for performance and can now handle lar
520
547
  The CLI automatically reads from your `.env` file for common settings:
521
548
 
522
549
  ```
523
- IPFS_GATEWAY=https://ipfs.io
550
+ IPFS_GATEWAY=https://get.hippius.network
524
551
  IPFS_API_URL=https://store.hippius.network
525
552
  SUBSTRATE_URL=wss://rpc.hippius.network
526
553
  SUBSTRATE_SEED_PHRASE="your twelve word seed phrase..."
@@ -534,55 +561,60 @@ HIPPIUS_ENCRYPT_BY_DEFAULT=true|false
534
561
  ### IPFS Operations
535
562
 
536
563
  ```python
564
+ import asyncio
537
565
  from hippius_sdk import IPFSClient
538
566
 
539
- # Initialize the IPFS client (uses Hippius relay node by default)
540
- ipfs_client = IPFSClient()
541
-
542
- # Or specify custom endpoints
543
- ipfs_client = IPFSClient(
544
- gateway="https://ipfs.io", # For downloads
545
- api_url="http://relay-fr.hippius.network:5001" # For uploads
546
- )
547
-
548
- # Upload a file
549
- result = ipfs_client.upload_file("path/to/your/file.txt")
550
- cid = result["cid"]
551
- size = result["size_formatted"]
552
-
553
- # Upload a directory
554
- dir_result = ipfs_client.upload_directory("path/to/your/directory")
555
- dir_cid = dir_result["cid"]
556
- file_count = dir_result["file_count"]
557
- total_size = dir_result["size_formatted"]
558
-
559
- # Download a file
560
- dl_result = ipfs_client.download_file(cid, "path/to/save/file.txt")
561
- success = dl_result["success"]
562
- elapsed_time = dl_result["elapsed_seconds"]
563
-
564
- # Check if a CID exists
565
- exists_result = ipfs_client.exists(cid)
566
- exists = exists_result["exists"]
567
- gateway_url = exists_result["gateway_url"]
568
-
569
- # Get file content directly
570
- content_result = ipfs_client.cat(cid)
571
- content = content_result["content"]
572
- is_text = content_result["is_text"]
573
- preview = content_result["text_preview"] if is_text else content_result["hex_preview"]
574
-
575
- # Pin a file
576
- pin_result = ipfs_client.pin(cid)
577
- success = pin_result["success"]
578
- message = pin_result["message"]
579
-
580
- # Format a CID
581
- formatted_cid = ipfs_client.format_cid("6261666b7265696134...") # Hex-encoded CID
582
- # Will return a proper formatted CID like "bafkrei..."
583
-
584
- # Format a file size
585
- human_readable = ipfs_client.format_size(1048576) # 1 MB
567
+ async def main():
568
+ # Initialize the IPFS client (uses Hippius relay node by default)
569
+ ipfs_client = IPFSClient()
570
+
571
+ # Or specify custom endpoints
572
+ ipfs_client = IPFSClient(
573
+ gateway="https://get.hippius.network", # For downloads
574
+ api_url="http://relay-fr.hippius.network:5001" # For uploads
575
+ )
576
+
577
+ # Upload a file
578
+ result = await ipfs_client.upload_file("path/to/your/file.txt")
579
+ cid = result["cid"]
580
+ size = result["size_formatted"]
581
+
582
+ # Upload a directory
583
+ dir_result = await ipfs_client.upload_directory("path/to/your/directory")
584
+ dir_cid = dir_result["cid"]
585
+ file_count = dir_result["file_count"]
586
+ total_size = dir_result["size_formatted"]
587
+
588
+ # Download a file
589
+ dl_result = await ipfs_client.download_file(cid, "path/to/save/file.txt")
590
+ success = dl_result["success"]
591
+ elapsed_time = dl_result["elapsed_seconds"]
592
+
593
+ # Check if a CID exists
594
+ exists_result = await ipfs_client.exists(cid)
595
+ exists = exists_result["exists"]
596
+ gateway_url = exists_result["gateway_url"]
597
+
598
+ # Get file content directly
599
+ content_result = await ipfs_client.cat(cid)
600
+ content = content_result["content"]
601
+ is_text = content_result["is_text"]
602
+ preview = content_result["text_preview"] if is_text else content_result["hex_preview"]
603
+
604
+ # Pin a file
605
+ pin_result = await ipfs_client.pin(cid)
606
+ success = pin_result["success"]
607
+ message = pin_result["message"]
608
+
609
+ # Format a CID (non-async utility function)
610
+ formatted_cid = ipfs_client.format_cid("6261666b7265696134...") # Hex-encoded CID
611
+ # Will return a proper formatted CID like "bafkrei..."
612
+
613
+ # Format a file size (non-async utility function)
614
+ human_readable = ipfs_client.format_size(1048576) # 1 MB
615
+
616
+ # Run the async function
617
+ asyncio.run(main())
586
618
  ```
587
619
 
588
620
  ### IPFS Connection Methods
@@ -611,7 +643,7 @@ hippius config list
611
643
  hippius config get ipfs gateway
612
644
 
613
645
  # Set a configuration value
614
- hippius config set ipfs gateway https://ipfs.io
646
+ hippius config set ipfs gateway https://get.hippius.network
615
647
 
616
648
  # Import settings from your .env file
617
649
  hippius config import-env
@@ -627,7 +659,7 @@ The configuration is organized in the following sections:
627
659
  ```json
628
660
  {
629
661
  "ipfs": {
630
- "gateway": "https://ipfs.io",
662
+ "gateway": "https://get.hippius.network",
631
663
  "api_url": "https://store.hippius.network",
632
664
  "local_ipfs": false
633
665
  },
@@ -664,6 +696,7 @@ hippius config import-env
664
696
  ### Using Configuration in Code
665
697
 
666
698
  ```python
699
+ import asyncio
667
700
  from hippius_sdk import get_config_value, set_config_value, HippiusClient
668
701
 
669
702
  # Get a configuration value
@@ -675,6 +708,13 @@ set_config_value("ipfs", "gateway", "https://dweb.link")
675
708
 
676
709
  # Client will automatically use configuration values
677
710
  client = HippiusClient()
711
+
712
+ async def main():
713
+ # Your async code here
714
+ pass
715
+
716
+ # Run the async function
717
+ asyncio.run(main())
678
718
  ```
679
719
 
680
720
  ## Development
@@ -743,6 +783,7 @@ To test the SDK components, you can create a small test script:
743
783
 
744
784
  ```python
745
785
  # test_script.py
786
+ import asyncio
746
787
  from hippius_sdk import HippiusClient
747
788
  from dotenv import load_dotenv
748
789
  import os
@@ -753,13 +794,17 @@ load_dotenv()
753
794
  # Create a client
754
795
  client = HippiusClient()
755
796
 
756
- # Test a simple operation
757
- print("Testing IPFS client...")
758
- try:
759
- result = client.exists("QmZ4tDuvesekSs4qM5ZBKpXiZGun7S2CYtEZRB3DYXkjGx")
760
- print(f"Result: {result}")
761
- except Exception as e:
762
- print(f"Error: {e}")
797
+ async def test_ipfs_client():
798
+ # Test a simple operation
799
+ print("Testing IPFS client...")
800
+ try:
801
+ result = await client.exists("QmZ4tDuvesekSs4qM5ZBKpXiZGun7S2CYtEZRB3DYXkjGx")
802
+ print(f"Result: {result}")
803
+ except Exception as e:
804
+ print(f"Error: {e}")
805
+
806
+ # Run the async function
807
+ asyncio.run(test_ipfs_client())
763
808
  ```
764
809
 
765
810
  Then run it:
@@ -878,6 +923,7 @@ This provides enhanced security by:
878
923
  When interacting with the Hippius SDK programmatically, you can provide the password when initializing clients:
879
924
 
880
925
  ```python
926
+ import asyncio
881
927
  from hippius_sdk import HippiusClient
882
928
 
883
929
  # The client will prompt for password when needed to decrypt the seed phrase
@@ -885,6 +931,13 @@ client = HippiusClient()
885
931
 
886
932
  # Or you can provide a password when initializing
887
933
  client = HippiusClient(seed_phrase_password="your-password")
934
+
935
+ async def main():
936
+ # Your async code here
937
+ pass
938
+
939
+ # Run the async function
940
+ asyncio.run(main())
888
941
  ```
889
942
 
890
943
  ### Multi-Account Management
@@ -922,25 +975,29 @@ Key features of the multi-account system:
922
975
  To use multiple accounts in your code:
923
976
 
924
977
  ```python
978
+ import asyncio
925
979
  from hippius_sdk import HippiusClient, set_active_account, list_accounts
926
980
 
927
- # List all accounts
928
- accounts = list_accounts()
929
- for name, data in accounts.items():
930
- print(f"{name}: {data.get('ss58_address')}")
931
-
932
- # Switch the active account
933
- set_active_account("my-validator")
934
-
935
- # Create a client with the active account
936
- client = HippiusClient(seed_phrase_password="your-password")
937
-
938
- # Or specify a different account to use
939
- client = HippiusClient(
940
- account_name="my-developer-account",
941
- seed_phrase_password="your-password"
942
- )
981
+ async def main():
982
+ # List all accounts
983
+ accounts = list_accounts()
984
+ for name, data in accounts.items():
985
+ print(f"{name}: {data.get('ss58_address')}")
986
+
987
+ # Switch the active account
988
+ set_active_account("my-validator")
989
+
990
+ # Create a client with the active account
991
+ client = HippiusClient(seed_phrase_password="your-password")
992
+
993
+ # Or specify a different account to use
994
+ client = HippiusClient(
995
+ account_name="my-developer-account",
996
+ seed_phrase_password="your-password"
997
+ )
998
+
999
+ # Run the async function
1000
+ asyncio.run(main())
943
1001
  ```
944
1002
 
945
1003
  The multi-account system makes it easier to manage multiple identities while maintaining security and convenience.
946
-