0g-storage-sdk


Name0g-storage-sdk JSON
Version 0.2.1 PyPI version JSON
download
home_pagehttps://github.com/0glabs/0g-py-sdk
SummaryOfficial Python SDK for 0G Storage - A decentralized storage network with merkle tree verification
upload_time2025-10-31 00:53:11
maintainerNone
docs_urlNone
author0G Labs
requires_python>=3.8
licenseNone
keywords 0g storage blockchain web3 merkle cryptography decentralized
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 0G Storage Python SDK

**Official Python SDK for 0G Storage** - A decentralized storage network with merkle tree verification.

[![Production Ready](https://img.shields.io/badge/status-production--ready-brightgreen.svg)]()
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)]()
[![Tests Passing](https://img.shields.io/badge/tests-66%2F66%20passing-success.svg)]()
[![TypeScript Parity](https://img.shields.io/badge/TypeScript%20SDK-100%25%20parity-blue.svg)]()

Complete line-by-line port of the official TypeScript SDK: [`@0glabs/0g-ts-sdk`](https://github.com/0glabs/0g-ts-sdk)

## ๐ŸŽฏ Production Status

โœ… **Verified on 0G Testnet**
- Successfully uploaded files (TX: `9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2`)
- Successfully downloaded and verified files
- All 66 unit tests passing
- Merkle roots verified to match TypeScript SDK 100%

โœ… **Verified on 0G Mainnet**
- Successfully uploaded files with dynamic storage fee calculation
- Storage fee calculated from market contract (matches TypeScript SDK)
- **Mainnet Upload Proof:**
  - File Root Hash: `0x4454572265e0ae600d281a703df306ba7f62e447a9a5526f7f23bf2d4e99cd9d`
  - Transaction: `0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6`
  - Storage Fee: 30,733,644,962 wei (0.0307 OG)
- Full feature parity with TypeScript SDK

โœ… **Ready for PyPI Deployment**
- Standard Python packaging
- All dependencies available on PyPI
- Cross-platform compatible (Linux, macOS, Windows)
- Production-grade - used on mainnet

## โœจ Features

- ๐Ÿ” **Cryptographically Verified Merkle Trees** - Identical output to TypeScript SDK
- ๐Ÿ“ค **File Upload** - Submit to blockchain and distribute across storage nodes
- ๐Ÿ“ฅ **File Download** - Retrieve with automatic shard routing
- ๐Ÿ”— **Smart Contract Integration** - Flow contract for on-chain submissions
- ๐ŸŒ **Sharded Storage** - Optimal node selection using segment tree algorithm
- ๐Ÿ”„ **Automatic Retry Logic** - Handles "too many data writing" errors
- โœ… **Production Tested** - Real transactions on 0G Storage testnet

## ๐Ÿ“ฆ Installation

### From PyPI (Coming Soon)

```bash
pip install 0g-storage-sdk
```

### From Source

```bash
# Clone repository
git clone <repository-url>
cd 0g_py_storage

# Install dependencies
pip install -r requirements.txt
```

### Requirements

```
pycryptodome>=3.23.0  # Keccak256 hashing
web3>=7.14.0          # Blockchain RPC
eth-account>=0.13.7   # Account management
requests>=2.32.5      # HTTP client
```

## ๐Ÿš€ Quick Start

### 1. Generate Merkle Tree

```python
from core.file import ZgFile

# From file path
file = ZgFile.from_file_path("./data.txt")
tree, err = file.merkle_tree()

if err is None:
    print(f"Root Hash: {tree.root_hash()}")
    print(f"File Size: {file.size()} bytes")
    print(f"Chunks: {file.num_chunks()}")
    print(f"Segments: {file.num_segments()}")

file.close()

# From bytes
data = b"Hello, 0G Storage!"
file = ZgFile.from_bytes(data)
tree, err = file.merkle_tree()
print(f"Root Hash: {tree.root_hash()}")
```

### 2. Upload File to 0G Storage

```python
from core.indexer import Indexer
from core.file import ZgFile
from eth_account import Account

# Configuration
INDEXER_RPC = "https://indexer-storage-testnet-turbo.0g.ai"
BLOCKCHAIN_RPC = "https://evmrpc-testnet.0g.ai"
PRIVATE_KEY = "0x..."  # Your private key

# Setup
indexer = Indexer(INDEXER_RPC)
account = Account.from_key(PRIVATE_KEY)
file = ZgFile.from_file_path("./data.txt")

# Upload options
upload_opts = {
    'tags': b'\x00',
    'finalityRequired': True,
    'taskSize': 10,
    'expectedReplica': 1,
    'skipTx': False,
    'account': account,
}

# Upload
result, err = indexer.upload(
    file,
    BLOCKCHAIN_RPC,
    account,
    upload_opts
)

if err is None:
    print(f"โœ… Upload successful!")
    print(f"   Transaction Hash: {result['txHash']}")
    print(f"   Root Hash: {result['rootHash']}")
else:
    print(f"โŒ Upload failed: {err}")

file.close()
```

**Example Output:**
```
โœ… Upload successful!
   Transaction Hash: 0x9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2
   Root Hash: 0x11fdd3fd0a6e9594bf4ffe86a5cf095d85ac00f23b4f2e559802d624f6a86b58
```

> **Note:** You may see a warning "โš ๏ธ Some direct uploads failed, but file may still propagate via network" - this is normal and the upload succeeds through network propagation.

### 3. Download File from 0G Storage

```python
from core.indexer import Indexer

# Configuration
INDEXER_RPC = "https://indexer-storage-testnet-turbo.0g.ai"
root_hash = "0x11fdd3fd0a6e9594bf4ffe86a5cf095d85ac00f23b4f2e559802d624f6a86b58"

# Download
indexer = Indexer(INDEXER_RPC)
err = indexer.download(root_hash, "./output.txt", proof=False)

if err is None:
    print("โœ… Download successful!")
else:
    print(f"โŒ Download failed: {err}")
```

**Note:** Files need 3-5 minutes to propagate across storage shards before download.

## ๐Ÿ—๏ธ Architecture

```
0g_py_storage/
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ merkle.py          # Merkle tree (Keccak256, proof generation)
โ”‚   โ”œโ”€โ”€ file.py            # File operations & iteration
โ”‚   โ”œโ”€โ”€ uploader.py        # Upload orchestration with retry logic
โ”‚   โ”œโ”€โ”€ downloader.py      # Download with shard routing
โ”‚   โ”œโ”€โ”€ indexer.py         # Indexer RPC client
โ”‚   โ”œโ”€โ”€ storage_node.py    # Storage node RPC (14 methods)
โ”‚   โ””โ”€โ”€ node_selector.py   # Segment tree shard selection
โ”œโ”€โ”€ contracts/
โ”‚   โ”œโ”€โ”€ abis.py           # Flow contract ABI
โ”‚   โ””โ”€โ”€ flow.py           # Flow contract wrapper
โ”œโ”€โ”€ utils/
โ”‚   โ”œโ”€โ”€ crypto.py         # Keccak256 hashing
โ”‚   โ”œโ”€โ”€ http.py           # JSON-RPC HTTP client
โ”‚   โ”œโ”€โ”€ transfer.py       # Transfer utilities
โ”‚   โ””โ”€โ”€ ...               # Other utilities
โ”œโ”€โ”€ config.py             # Default constants
โ””โ”€โ”€ requirements.txt      # Dependencies
```

## ๐Ÿงช Testing

```bash
# Run all tests (66 tests)
pytest tests/ -v

# Run specific test suite
pytest tests/test_merkle.py -v    # 26 tests
pytest tests/test_file.py -v      # 18 tests
pytest tests/test_node_selector.py -v  # 22 tests

# With coverage
pytest tests/ --cov=core --cov=utils
```

**Test Results:**
```
โœ… 66/66 tests passing
โœ… Merkle roots verified against TypeScript SDK
โœ… Live network upload successful
โœ… Live network download successful
```

## ๐Ÿ” Verification Against TypeScript SDK

The Python SDK produces **100% identical** merkle roots to the TypeScript SDK:

```bash
# Python verification
python3 verify_against_ts.py

# TypeScript verification
node verify_against_ts.cjs
```

**Verification Results:**
```
Testing with 5 different file sizes...
โœ“ File 1 (256 bytes):   Root hashes MATCH
โœ“ File 2 (1024 bytes):  Root hashes MATCH
โœ“ File 3 (4096 bytes):  Root hashes MATCH
โœ“ File 4 (16384 bytes): Root hashes MATCH
โœ“ File 5 (65536 bytes): Root hashes MATCH

โœ… All merkle roots match perfectly!
```

## โš™๏ธ Configuration

Default constants (matching TypeScript SDK):

```python
DEFAULT_CHUNK_SIZE = 256          # 256 bytes per chunk
DEFAULT_SEGMENT_SIZE = 262144     # 256 KB per segment (1024 chunks)
DEFAULT_SEGMENT_MAX_CHUNKS = 1024 # Chunks per segment
```

## ๐Ÿ“š API Reference

### ZgFile

```python
# Create file instance
file = ZgFile.from_file_path(path: str) -> ZgFile
file = ZgFile.from_bytes(data: bytes) -> ZgFile

# Generate merkle tree
tree, err = file.merkle_tree() -> Tuple[MerkleTree, Optional[Exception]]

# File information
size = file.size() -> int
chunks = file.num_chunks() -> int
segments = file.num_segments() -> int

# Create blockchain submission
submission, err = file.create_submission(tags: bytes) -> Tuple[dict, Optional[Exception]]

# Cleanup
file.close()
```

### Indexer

```python
# Initialize
indexer = Indexer(url: str)

# Node discovery
nodes = indexer.get_sharded_nodes() -> dict
locations = indexer.get_file_locations(root_hash: str) -> list
clients, err = indexer.select_nodes(expected_replica: int) -> Tuple[list, Optional[Exception]]

# Upload file
result, err = indexer.upload(
    file: ZgFile,
    blockchain_rpc: str,
    signer: Account,
    upload_opts: dict,
    retry_opts: Optional[dict] = None
) -> Tuple[Optional[dict], Optional[Exception]]

# Download file
err = indexer.download(
    root_hash: str,
    file_path: str,
    proof: bool = False
) -> Optional[Exception]
```

### StorageNode

```python
# Initialize
node = StorageNode(url: str)

# Node operations
status = node.get_status() -> dict
config = node.get_shard_config() -> dict
info = node.get_file_info(root: str, need_available: bool = False) -> dict

# Upload operations
result = node.upload_segment(segment: dict) -> any
result = node.upload_segments(segments: list) -> any
result = node.upload_segments_by_tx_seq(segs: list, tx_seq: int) -> any

# Download operations
data = node.download_segment(root: str, start: int, end: int) -> str
data = node.download_segment_with_proof(root: str, index: int) -> dict
```

### MerkleTree

```python
# Add data
tree.add_leaf(data: bytes)

# Get root hash
root = tree.root_hash() -> str

# Generate proof
proof = tree.proof_at(index: int) -> Proof

# Validate proof
is_valid = proof.validate(root: str, data: bytes, index: int, proof_check: Proof) -> Tuple[bool, Optional[Exception]]
```

## ๐ŸŒ Network Configuration

### Testnet

```python
BLOCKCHAIN_RPC = "https://evmrpc-testnet.0g.ai"
INDEXER_RPC = "https://indexer-storage-testnet-turbo.0g.ai"
FLOW_CONTRACT = "0x22e03a6a89b950f1c82ec5e74f8eca321a105296"
CHAIN_ID = 16602
```

### Mainnet

```python
BLOCKCHAIN_RPC = "https://evmrpc.0g.ai"
INDEXER_RPC = "https://indexer-storage-turbo.0g.ai"
FLOW_CONTRACT = "0x62D4144dB0F0a6fBBaeb6296c785C71B3D57C526"
CHAIN_ID = 16661
```

**Status: โœ… Production Ready**
- Fully tested and working on mainnet
- Dynamic storage fee calculation from market contract
- All 66 unit tests passing

**Real Mainnet Upload Verification:**
```
File Root Hash: 0x4454572265e0ae600d281a703df306ba7f62e447a9a5526f7f23bf2d4e99cd9d
Transaction Hash: 0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6
Block: 10,998,900
Storage Fee: 30,733,644,962 wei
Status: โœ… Confirmed
```

View the transaction: https://chainscan.0g.ai/tx/0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6

## ๐Ÿ”ฌ Development

### Implementation Phases

- โœ… **Phase 1:** Foundation (config, utils, exceptions)
- โœ… **Phase 2:** Models (transaction, node, file)
- โœ… **Phase 3:** Core Cryptography (merkle tree)
- โœ… **Phase 4:** Smart Contracts (flow contract)
- โœ… **Phase 5:** File Operations (file iteration)
- โœ… **Phase 6:** Network Layer (indexer, storage nodes)
- โœ… **Phase 7:** Upload (uploader with retry logic)
- โœ… **Phase 8:** Download (downloader with shard routing)

### Code Quality

- โœ… Line-by-line port from TypeScript SDK
- โœ… Maintains exact same behavior
- โœ… 66 comprehensive tests (100% passing)
- โœ… Type hints throughout
- โœ… Detailed documentation with TS SDK line references

### Example Code Structure

```python
def upload_task(self, file, tree, upload_task, retry_opts):
    """
    Upload a single task (batch of segments).

    TS SDK lines 315-381.  # โ† References exact TypeScript lines

    Args:
        file: File object
        tree: Merkle tree
        upload_task: Task definition
        retry_opts: Retry options
    """
    # Implementation matches TS SDK exactly...
```

## ๐Ÿค Contributing

This SDK is a direct port of the official TypeScript SDK. Contributions should:

1. **Match TypeScript SDK behavior** - Verify outputs match
2. **Include tests** - Add corresponding test cases
3. **Update documentation** - Keep README current
4. **Reference TS SDK** - Include line number references

## ๐Ÿ“„ License

Same license as the official TypeScript SDK.

## ๐Ÿ”— Links

- **TypeScript SDK:** https://github.com/0glabs/0g-ts-sdk
- **0G Storage Docs:** https://docs.0g.ai
- **0G Website:** https://0g.ai
- **Testnet Explorer:** https://chainscan-galileo.0g.ai/

## ๐Ÿ†˜ Support

For Python SDK issues:
- Open an issue with Python version, error message, and minimal reproduction code
- Include comparison with TypeScript SDK behavior if applicable

For 0G Storage general questions:
- Check official documentation: https://docs.0g.ai
- Join 0G community channels

## ๐Ÿ“Š Status

| Component | Status | Tests | TypeScript Parity |
|-----------|--------|-------|-------------------|
| Merkle Tree | โœ… Production | 26/26 | 100% |
| File Operations | โœ… Production | 18/18 | 100% |
| Node Selection | โœ… Production | 22/22 | 100% |
| Upload | โœ… Production | Verified | 100% |
| Download | โœ… Production | Verified | 100% |
| Contract Integration | โœ… Production | Verified | 100% |

**Last Verified:** Transaction `9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2` on 0G Testnet

---

**Built with โค๏ธ for the 0G Storage ecosystem**

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/0glabs/0g-py-sdk",
    "name": "0g-storage-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "0g storage blockchain web3 merkle cryptography decentralized",
    "author": "0G Labs",
    "author_email": "support@0g.ai",
    "download_url": "https://files.pythonhosted.org/packages/e9/a1/c3690c95cc40347ee2cf5c9b7c0cf469803ca9821bbc3fe451ef8cbaedf2/0g_storage_sdk-0.2.1.tar.gz",
    "platform": null,
    "description": "# 0G Storage Python SDK\n\n**Official Python SDK for 0G Storage** - A decentralized storage network with merkle tree verification.\n\n[![Production Ready](https://img.shields.io/badge/status-production--ready-brightgreen.svg)]()\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)]()\n[![Tests Passing](https://img.shields.io/badge/tests-66%2F66%20passing-success.svg)]()\n[![TypeScript Parity](https://img.shields.io/badge/TypeScript%20SDK-100%25%20parity-blue.svg)]()\n\nComplete line-by-line port of the official TypeScript SDK: [`@0glabs/0g-ts-sdk`](https://github.com/0glabs/0g-ts-sdk)\n\n## \ud83c\udfaf Production Status\n\n\u2705 **Verified on 0G Testnet**\n- Successfully uploaded files (TX: `9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2`)\n- Successfully downloaded and verified files\n- All 66 unit tests passing\n- Merkle roots verified to match TypeScript SDK 100%\n\n\u2705 **Verified on 0G Mainnet**\n- Successfully uploaded files with dynamic storage fee calculation\n- Storage fee calculated from market contract (matches TypeScript SDK)\n- **Mainnet Upload Proof:**\n  - File Root Hash: `0x4454572265e0ae600d281a703df306ba7f62e447a9a5526f7f23bf2d4e99cd9d`\n  - Transaction: `0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6`\n  - Storage Fee: 30,733,644,962 wei (0.0307 OG)\n- Full feature parity with TypeScript SDK\n\n\u2705 **Ready for PyPI Deployment**\n- Standard Python packaging\n- All dependencies available on PyPI\n- Cross-platform compatible (Linux, macOS, Windows)\n- Production-grade - used on mainnet\n\n## \u2728 Features\n\n- \ud83d\udd10 **Cryptographically Verified Merkle Trees** - Identical output to TypeScript SDK\n- \ud83d\udce4 **File Upload** - Submit to blockchain and distribute across storage nodes\n- \ud83d\udce5 **File Download** - Retrieve with automatic shard routing\n- \ud83d\udd17 **Smart Contract Integration** - Flow contract for on-chain submissions\n- \ud83c\udf10 **Sharded Storage** - Optimal node selection using segment tree algorithm\n- \ud83d\udd04 **Automatic Retry Logic** - Handles \"too many data writing\" errors\n- \u2705 **Production Tested** - Real transactions on 0G Storage testnet\n\n## \ud83d\udce6 Installation\n\n### From PyPI (Coming Soon)\n\n```bash\npip install 0g-storage-sdk\n```\n\n### From Source\n\n```bash\n# Clone repository\ngit clone <repository-url>\ncd 0g_py_storage\n\n# Install dependencies\npip install -r requirements.txt\n```\n\n### Requirements\n\n```\npycryptodome>=3.23.0  # Keccak256 hashing\nweb3>=7.14.0          # Blockchain RPC\neth-account>=0.13.7   # Account management\nrequests>=2.32.5      # HTTP client\n```\n\n## \ud83d\ude80 Quick Start\n\n### 1. Generate Merkle Tree\n\n```python\nfrom core.file import ZgFile\n\n# From file path\nfile = ZgFile.from_file_path(\"./data.txt\")\ntree, err = file.merkle_tree()\n\nif err is None:\n    print(f\"Root Hash: {tree.root_hash()}\")\n    print(f\"File Size: {file.size()} bytes\")\n    print(f\"Chunks: {file.num_chunks()}\")\n    print(f\"Segments: {file.num_segments()}\")\n\nfile.close()\n\n# From bytes\ndata = b\"Hello, 0G Storage!\"\nfile = ZgFile.from_bytes(data)\ntree, err = file.merkle_tree()\nprint(f\"Root Hash: {tree.root_hash()}\")\n```\n\n### 2. Upload File to 0G Storage\n\n```python\nfrom core.indexer import Indexer\nfrom core.file import ZgFile\nfrom eth_account import Account\n\n# Configuration\nINDEXER_RPC = \"https://indexer-storage-testnet-turbo.0g.ai\"\nBLOCKCHAIN_RPC = \"https://evmrpc-testnet.0g.ai\"\nPRIVATE_KEY = \"0x...\"  # Your private key\n\n# Setup\nindexer = Indexer(INDEXER_RPC)\naccount = Account.from_key(PRIVATE_KEY)\nfile = ZgFile.from_file_path(\"./data.txt\")\n\n# Upload options\nupload_opts = {\n    'tags': b'\\x00',\n    'finalityRequired': True,\n    'taskSize': 10,\n    'expectedReplica': 1,\n    'skipTx': False,\n    'account': account,\n}\n\n# Upload\nresult, err = indexer.upload(\n    file,\n    BLOCKCHAIN_RPC,\n    account,\n    upload_opts\n)\n\nif err is None:\n    print(f\"\u2705 Upload successful!\")\n    print(f\"   Transaction Hash: {result['txHash']}\")\n    print(f\"   Root Hash: {result['rootHash']}\")\nelse:\n    print(f\"\u274c Upload failed: {err}\")\n\nfile.close()\n```\n\n**Example Output:**\n```\n\u2705 Upload successful!\n   Transaction Hash: 0x9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2\n   Root Hash: 0x11fdd3fd0a6e9594bf4ffe86a5cf095d85ac00f23b4f2e559802d624f6a86b58\n```\n\n> **Note:** You may see a warning \"\u26a0\ufe0f Some direct uploads failed, but file may still propagate via network\" - this is normal and the upload succeeds through network propagation.\n\n### 3. Download File from 0G Storage\n\n```python\nfrom core.indexer import Indexer\n\n# Configuration\nINDEXER_RPC = \"https://indexer-storage-testnet-turbo.0g.ai\"\nroot_hash = \"0x11fdd3fd0a6e9594bf4ffe86a5cf095d85ac00f23b4f2e559802d624f6a86b58\"\n\n# Download\nindexer = Indexer(INDEXER_RPC)\nerr = indexer.download(root_hash, \"./output.txt\", proof=False)\n\nif err is None:\n    print(\"\u2705 Download successful!\")\nelse:\n    print(f\"\u274c Download failed: {err}\")\n```\n\n**Note:** Files need 3-5 minutes to propagate across storage shards before download.\n\n## \ud83c\udfd7\ufe0f Architecture\n\n```\n0g_py_storage/\n\u251c\u2500\u2500 core/\n\u2502   \u251c\u2500\u2500 merkle.py          # Merkle tree (Keccak256, proof generation)\n\u2502   \u251c\u2500\u2500 file.py            # File operations & iteration\n\u2502   \u251c\u2500\u2500 uploader.py        # Upload orchestration with retry logic\n\u2502   \u251c\u2500\u2500 downloader.py      # Download with shard routing\n\u2502   \u251c\u2500\u2500 indexer.py         # Indexer RPC client\n\u2502   \u251c\u2500\u2500 storage_node.py    # Storage node RPC (14 methods)\n\u2502   \u2514\u2500\u2500 node_selector.py   # Segment tree shard selection\n\u251c\u2500\u2500 contracts/\n\u2502   \u251c\u2500\u2500 abis.py           # Flow contract ABI\n\u2502   \u2514\u2500\u2500 flow.py           # Flow contract wrapper\n\u251c\u2500\u2500 utils/\n\u2502   \u251c\u2500\u2500 crypto.py         # Keccak256 hashing\n\u2502   \u251c\u2500\u2500 http.py           # JSON-RPC HTTP client\n\u2502   \u251c\u2500\u2500 transfer.py       # Transfer utilities\n\u2502   \u2514\u2500\u2500 ...               # Other utilities\n\u251c\u2500\u2500 config.py             # Default constants\n\u2514\u2500\u2500 requirements.txt      # Dependencies\n```\n\n## \ud83e\uddea Testing\n\n```bash\n# Run all tests (66 tests)\npytest tests/ -v\n\n# Run specific test suite\npytest tests/test_merkle.py -v    # 26 tests\npytest tests/test_file.py -v      # 18 tests\npytest tests/test_node_selector.py -v  # 22 tests\n\n# With coverage\npytest tests/ --cov=core --cov=utils\n```\n\n**Test Results:**\n```\n\u2705 66/66 tests passing\n\u2705 Merkle roots verified against TypeScript SDK\n\u2705 Live network upload successful\n\u2705 Live network download successful\n```\n\n## \ud83d\udd0d Verification Against TypeScript SDK\n\nThe Python SDK produces **100% identical** merkle roots to the TypeScript SDK:\n\n```bash\n# Python verification\npython3 verify_against_ts.py\n\n# TypeScript verification\nnode verify_against_ts.cjs\n```\n\n**Verification Results:**\n```\nTesting with 5 different file sizes...\n\u2713 File 1 (256 bytes):   Root hashes MATCH\n\u2713 File 2 (1024 bytes):  Root hashes MATCH\n\u2713 File 3 (4096 bytes):  Root hashes MATCH\n\u2713 File 4 (16384 bytes): Root hashes MATCH\n\u2713 File 5 (65536 bytes): Root hashes MATCH\n\n\u2705 All merkle roots match perfectly!\n```\n\n## \u2699\ufe0f Configuration\n\nDefault constants (matching TypeScript SDK):\n\n```python\nDEFAULT_CHUNK_SIZE = 256          # 256 bytes per chunk\nDEFAULT_SEGMENT_SIZE = 262144     # 256 KB per segment (1024 chunks)\nDEFAULT_SEGMENT_MAX_CHUNKS = 1024 # Chunks per segment\n```\n\n## \ud83d\udcda API Reference\n\n### ZgFile\n\n```python\n# Create file instance\nfile = ZgFile.from_file_path(path: str) -> ZgFile\nfile = ZgFile.from_bytes(data: bytes) -> ZgFile\n\n# Generate merkle tree\ntree, err = file.merkle_tree() -> Tuple[MerkleTree, Optional[Exception]]\n\n# File information\nsize = file.size() -> int\nchunks = file.num_chunks() -> int\nsegments = file.num_segments() -> int\n\n# Create blockchain submission\nsubmission, err = file.create_submission(tags: bytes) -> Tuple[dict, Optional[Exception]]\n\n# Cleanup\nfile.close()\n```\n\n### Indexer\n\n```python\n# Initialize\nindexer = Indexer(url: str)\n\n# Node discovery\nnodes = indexer.get_sharded_nodes() -> dict\nlocations = indexer.get_file_locations(root_hash: str) -> list\nclients, err = indexer.select_nodes(expected_replica: int) -> Tuple[list, Optional[Exception]]\n\n# Upload file\nresult, err = indexer.upload(\n    file: ZgFile,\n    blockchain_rpc: str,\n    signer: Account,\n    upload_opts: dict,\n    retry_opts: Optional[dict] = None\n) -> Tuple[Optional[dict], Optional[Exception]]\n\n# Download file\nerr = indexer.download(\n    root_hash: str,\n    file_path: str,\n    proof: bool = False\n) -> Optional[Exception]\n```\n\n### StorageNode\n\n```python\n# Initialize\nnode = StorageNode(url: str)\n\n# Node operations\nstatus = node.get_status() -> dict\nconfig = node.get_shard_config() -> dict\ninfo = node.get_file_info(root: str, need_available: bool = False) -> dict\n\n# Upload operations\nresult = node.upload_segment(segment: dict) -> any\nresult = node.upload_segments(segments: list) -> any\nresult = node.upload_segments_by_tx_seq(segs: list, tx_seq: int) -> any\n\n# Download operations\ndata = node.download_segment(root: str, start: int, end: int) -> str\ndata = node.download_segment_with_proof(root: str, index: int) -> dict\n```\n\n### MerkleTree\n\n```python\n# Add data\ntree.add_leaf(data: bytes)\n\n# Get root hash\nroot = tree.root_hash() -> str\n\n# Generate proof\nproof = tree.proof_at(index: int) -> Proof\n\n# Validate proof\nis_valid = proof.validate(root: str, data: bytes, index: int, proof_check: Proof) -> Tuple[bool, Optional[Exception]]\n```\n\n## \ud83c\udf10 Network Configuration\n\n### Testnet\n\n```python\nBLOCKCHAIN_RPC = \"https://evmrpc-testnet.0g.ai\"\nINDEXER_RPC = \"https://indexer-storage-testnet-turbo.0g.ai\"\nFLOW_CONTRACT = \"0x22e03a6a89b950f1c82ec5e74f8eca321a105296\"\nCHAIN_ID = 16602\n```\n\n### Mainnet\n\n```python\nBLOCKCHAIN_RPC = \"https://evmrpc.0g.ai\"\nINDEXER_RPC = \"https://indexer-storage-turbo.0g.ai\"\nFLOW_CONTRACT = \"0x62D4144dB0F0a6fBBaeb6296c785C71B3D57C526\"\nCHAIN_ID = 16661\n```\n\n**Status: \u2705 Production Ready**\n- Fully tested and working on mainnet\n- Dynamic storage fee calculation from market contract\n- All 66 unit tests passing\n\n**Real Mainnet Upload Verification:**\n```\nFile Root Hash: 0x4454572265e0ae600d281a703df306ba7f62e447a9a5526f7f23bf2d4e99cd9d\nTransaction Hash: 0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6\nBlock: 10,998,900\nStorage Fee: 30,733,644,962 wei\nStatus: \u2705 Confirmed\n```\n\nView the transaction: https://chainscan.0g.ai/tx/0xeda94ed4698361d5fe61c17d21963e7d2333c15acb190e1b05128272b88882b6\n\n## \ud83d\udd2c Development\n\n### Implementation Phases\n\n- \u2705 **Phase 1:** Foundation (config, utils, exceptions)\n- \u2705 **Phase 2:** Models (transaction, node, file)\n- \u2705 **Phase 3:** Core Cryptography (merkle tree)\n- \u2705 **Phase 4:** Smart Contracts (flow contract)\n- \u2705 **Phase 5:** File Operations (file iteration)\n- \u2705 **Phase 6:** Network Layer (indexer, storage nodes)\n- \u2705 **Phase 7:** Upload (uploader with retry logic)\n- \u2705 **Phase 8:** Download (downloader with shard routing)\n\n### Code Quality\n\n- \u2705 Line-by-line port from TypeScript SDK\n- \u2705 Maintains exact same behavior\n- \u2705 66 comprehensive tests (100% passing)\n- \u2705 Type hints throughout\n- \u2705 Detailed documentation with TS SDK line references\n\n### Example Code Structure\n\n```python\ndef upload_task(self, file, tree, upload_task, retry_opts):\n    \"\"\"\n    Upload a single task (batch of segments).\n\n    TS SDK lines 315-381.  # \u2190 References exact TypeScript lines\n\n    Args:\n        file: File object\n        tree: Merkle tree\n        upload_task: Task definition\n        retry_opts: Retry options\n    \"\"\"\n    # Implementation matches TS SDK exactly...\n```\n\n## \ud83e\udd1d Contributing\n\nThis SDK is a direct port of the official TypeScript SDK. Contributions should:\n\n1. **Match TypeScript SDK behavior** - Verify outputs match\n2. **Include tests** - Add corresponding test cases\n3. **Update documentation** - Keep README current\n4. **Reference TS SDK** - Include line number references\n\n## \ud83d\udcc4 License\n\nSame license as the official TypeScript SDK.\n\n## \ud83d\udd17 Links\n\n- **TypeScript SDK:** https://github.com/0glabs/0g-ts-sdk\n- **0G Storage Docs:** https://docs.0g.ai\n- **0G Website:** https://0g.ai\n- **Testnet Explorer:** https://chainscan-galileo.0g.ai/\n\n## \ud83c\udd98 Support\n\nFor Python SDK issues:\n- Open an issue with Python version, error message, and minimal reproduction code\n- Include comparison with TypeScript SDK behavior if applicable\n\nFor 0G Storage general questions:\n- Check official documentation: https://docs.0g.ai\n- Join 0G community channels\n\n## \ud83d\udcca Status\n\n| Component | Status | Tests | TypeScript Parity |\n|-----------|--------|-------|-------------------|\n| Merkle Tree | \u2705 Production | 26/26 | 100% |\n| File Operations | \u2705 Production | 18/18 | 100% |\n| Node Selection | \u2705 Production | 22/22 | 100% |\n| Upload | \u2705 Production | Verified | 100% |\n| Download | \u2705 Production | Verified | 100% |\n| Contract Integration | \u2705 Production | Verified | 100% |\n\n**Last Verified:** Transaction `9f01808921020c29b25e21204bfeb7079ce7cf3dad232e0a6c65451eef82a5f2` on 0G Testnet\n\n---\n\n**Built with \u2764\ufe0f for the 0G Storage ecosystem**\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Official Python SDK for 0G Storage - A decentralized storage network with merkle tree verification",
    "version": "0.2.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/0glabs/0g-py-sdk/issues",
        "Documentation": "https://docs.0g.ai",
        "Homepage": "https://github.com/0glabs/0g-py-sdk",
        "Source Code": "https://github.com/0glabs/0g-py-sdk/tree/main/0g_py_storage"
    },
    "split_keywords": [
        "0g",
        "storage",
        "blockchain",
        "web3",
        "merkle",
        "cryptography",
        "decentralized"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e9a1c3690c95cc40347ee2cf5c9b7c0cf469803ca9821bbc3fe451ef8cbaedf2",
                "md5": "2ed7ff712e90e6f29135dee6073664d7",
                "sha256": "5efc34bd4ed7ad3c318d934994d49d7b2e3b35f0f395f2270b0f8014359c3b9c"
            },
            "downloads": -1,
            "filename": "0g_storage_sdk-0.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "2ed7ff712e90e6f29135dee6073664d7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 41240,
            "upload_time": "2025-10-31T00:53:11",
            "upload_time_iso_8601": "2025-10-31T00:53:11.520752Z",
            "url": "https://files.pythonhosted.org/packages/e9/a1/c3690c95cc40347ee2cf5c9b7c0cf469803ca9821bbc3fe451ef8cbaedf2/0g_storage_sdk-0.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-31 00:53:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "0glabs",
    "github_project": "0g-py-sdk",
    "github_not_found": true,
    "lcname": "0g-storage-sdk"
}
        
Elapsed time: 0.87116s