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.
- {hippius-0.2.2 → hippius-0.2.4}/PKG-INFO +213 -156
- {hippius-0.2.2 → hippius-0.2.4}/README.md +214 -157
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/__init__.py +10 -21
- hippius-0.2.4/hippius_sdk/cli.py +455 -0
- hippius-0.2.4/hippius_sdk/cli_assets.py +10 -0
- hippius-0.2.4/hippius_sdk/cli_handlers.py +2773 -0
- hippius-0.2.4/hippius_sdk/cli_parser.py +607 -0
- hippius-0.2.4/hippius_sdk/cli_rich.py +247 -0
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/client.py +70 -22
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/config.py +109 -142
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/ipfs.py +435 -58
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/ipfs_core.py +22 -1
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/substrate.py +234 -553
- {hippius-0.2.2 → hippius-0.2.4}/hippius_sdk/utils.py +84 -2
- {hippius-0.2.2 → hippius-0.2.4}/pyproject.toml +2 -1
- hippius-0.2.2/hippius_sdk/cli.py +0 -2800
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: hippius
|
3
|
-
Version: 0.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://
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
print(f"File
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
print(f"
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
print(f"
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
print(f"
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
print(f"
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
161
|
-
|
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
|
-
|
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
|
-
|
175
|
-
|
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
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
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://
|
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://
|
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
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
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://
|
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://
|
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
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
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
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
client
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
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
|
-
|