Python SDK for interacting with the Ardrive Turbo Upload and Payment Service
Project description
Turbo Python SDK
A Python SDK for interacting with the ArDrive Turbo Upload service, supporting both Ethereum and Arweave signers for permanent data storage on Arweave.
Get Started
Installation
pip install turbo-sdk
Quick Start
Ethereum Usage
from turbo_sdk import Turbo, EthereumSigner
# Create Ethereum signer
signer = EthereumSigner("0x1234567890abcdef...") # Your private key
# Create Turbo client
turbo = Turbo(signer, network="mainnet")
# Upload data
result = turbo.upload(b"Hello, Turbo!", tags=[
{"name": "Content-Type", "value": "text/plain"},
{"name": "App-Name", "value": "MyApp"}
])
print(f"✅ Uploaded! TX ID: {result.id}")
print(f"🌐 View at: https://arweave.net/{result.id}")
Arweave Usage
import json
from turbo_sdk import Turbo, ArweaveSigner
# Load Arweave wallet (JWK format)
with open("test-wallet.json") as f:
jwk = json.load(f)
# Create Arweave signer
signer = ArweaveSigner(jwk)
# Create Turbo client
turbo = Turbo(signer, network="mainnet")
# Upload data
result = turbo.upload(b"Hello from Arweave!", tags=[
{"name": "Content-Type", "value": "text/plain"}
])
print(f"✅ Uploaded! URI: ar://{result.id}")
APIs
Core Classes
Turbo(signer, network="mainnet", upload_url=None, payment_url=None)
Main client for interacting with Turbo services.
Parameters:
signer: EitherEthereumSignerorArweaveSignerinstancenetwork:"mainnet"or"testnet"(default:"mainnet")upload_url: Optional custom upload service URL (overrides network default)payment_url: Optional custom payment service URL (overrides network default)
# Using default URLs (mainnet)
turbo = Turbo(signer)
# Using testnet
turbo = Turbo(signer, network="testnet")
# Using custom URLs
turbo = Turbo(signer, upload_url="https://my-upload-service.example.com")
Methods:
upload(data=None, tags=None, on_progress=None, chunking=None, data_size=None, stream_factory=None) -> TurboUploadResponse
Upload data to the Turbo datachain. Supports both small files (single request) and large files (chunked multipart upload).
Parameters:
data: Data to upload (bytesor file-likeBinaryIOobject)tags: Optional list of metadata tagson_progress: Optional callback(processed_bytes, total_bytes) -> Nonechunking: OptionalChunkingParamsfor upload configurationdata_size: Required whendatais a file-like object or when usingstream_factorystream_factory: Optional callable that returns a freshBinaryIOstream each time it's called. Use this for non-seekable streams or when you want to avoid loading the entire file into memory.
# Simple upload
result = turbo.upload(
data=b"Your data here",
tags=[
{"name": "Content-Type", "value": "application/json"},
{"name": "App-Name", "value": "MyApp"}
]
)
Returns: TurboUploadResponse
@dataclass
class TurboUploadResponse:
id: str # Transaction ID
owner: str # Owner address
data_caches: List[str] # Cache endpoints
fast_finality_indexes: List[str] # Fast finality indexes
winc: str # Winston credits cost
Large File Uploads with Progress
For files >= 5 MiB, the SDK automatically uses chunked multipart uploads. Use stream_factory to avoid loading the entire file into memory. A factory is needed because the stream is consumed twice — once for signing and once for uploading — so the SDK calls it each time to get a fresh stream.
import os
def on_progress(processed: int, total: int):
pct = (processed / total) * 100
print(f"Upload progress: {pct:.1f}%")
file_path = "large-video.mp4"
result = turbo.upload(
stream_factory=lambda: open(file_path, "rb"),
data_size=os.path.getsize(file_path),
tags=[{"name": "Content-Type", "value": "video/mp4"}],
on_progress=on_progress,
)
Chunking Configuration
Use ChunkingParams to customize chunked upload behavior:
from turbo_sdk import ChunkingParams
result = turbo.upload(
data=large_data,
chunking=ChunkingParams(
chunk_size=10 * 1024 * 1024, # 10 MiB chunks (default: 5 MiB)
max_chunk_concurrency=3, # Parallel chunk uploads (default: 1)
chunking_mode="auto", # "auto", "force", or "disabled"
),
on_progress=lambda p, t: print(f"{p}/{t} bytes"),
)
ChunkingParams options:
chunk_size: Chunk size in bytes (5-500 MiB, default: 5 MiB)max_chunk_concurrency: Number of parallel chunk uploads (default: 1)chunking_mode:"auto"(default): Use chunked upload for files >= 5 MiB"force": Always use chunked upload"disabled": Always use single request upload
get_balance(address=None) -> TurboBalanceResponse
Get winston credit balance. Uses signed request for authenticated balance check when no address specified.
# Check your own balance (signed request)
balance = turbo.get_balance()
print(f"Balance: {balance.winc} winc")
# Check another address (no signature needed)
other_balance = turbo.get_balance("0x742d35Cc6635C0532925a3b8C17af2e95C5Aca4A")
print(f"Other balance: {other_balance.winc} winc")
Returns: TurboBalanceResponse
@dataclass
class TurboBalanceResponse:
winc: str # Available winston credits
controlled_winc: str # Controlled amount
effective_balance: str # Effective balance including shared credits
get_upload_price(byte_count) -> int
Get the cost to upload data of a specific size.
cost = turbo.get_upload_price(1024) # Cost for 1KB
print(f"Upload cost: {cost} winc")
Signers
EthereumSigner(private_key)
Ethereum signer using ECDSA signatures.
Parameters:
private_key(str): Hex private key with or without0xprefix
signer = EthereumSigner("0x1234567890abcdef...")
ArweaveSigner(jwk)
Arweave signer using RSA-PSS signatures.
Parameters:
jwk(dict): Arweave wallet in JWK format
signer = ArweaveSigner({
"kty": "RSA",
"n": "...",
"e": "AQAB",
"d": "...",
# ... other JWK fields
})
Signer Methods
Both signers provide:
get_wallet_address() -> str
Get the wallet address for the signer.
address = signer.get_wallet_address()
print(f"Wallet address: {address}")
create_signed_headers() -> dict
Create signed headers for authenticated API requests.
headers = signer.create_signed_headers()
Exceptions
The SDK provides specific exceptions for error handling:
from turbo_sdk import UnderfundedError, ChunkedUploadError
try:
result = turbo.upload(large_data)
except UnderfundedError:
print("Insufficient balance - please top up your account")
except ChunkedUploadError as e:
print(f"Upload failed: {e}")
Exception types:
ChunkedUploadError: Base exception for chunked upload failuresUnderfundedError: Account has insufficient balance (HTTP 402)UploadValidationError: Upload validation failed (INVALID status)UploadFinalizationError: Finalization timed out or failed
Developers
Setup
- Create a virtual environment:
python -m venv venv
source venv/bin/activate
- Install dependencies:
pip install -e ".[dev]"
- Run tests:
pytest
With coverage
pytest --cov=turbo_sdk
- Lint and format:
black turbo_sdk tests
flake8 turbo_sdk tests
- Run performance benchmarks (requires funded wallet):
export TURBO_TEST_WALLET=/path/to/wallet.json
export TURBO_UPLOAD_URL=https://upload.ardrive.dev # optional, defaults to testnet
pytest -m performance -v -s
The test suite includes comprehensive unit tests for all components. Performance tests measure real upload throughput against the Turbo service.
Publishing
Releases are published to PyPI via the GitHub Actions workflow at .github/workflows/release.yml. It runs on release events or can be triggered manually via workflow_dispatch.
There is no automated versioning. Before publishing, update the version field in pyproject.toml to reflect the new release:
[project]
version = "0.0.5"
Steps to release:
- Merge feature branches into
alpha. - Review the commits and update the
versionfield inpyproject.tomlaccordingly. - Push to the
alphabranch. - Manually run the release workflow at
.github/workflows/release.ymlviaworkflow_dispatch.
The workflow runs tests across Python 3.8-3.12, builds the package, and publishes to PyPI using trusted OIDC publishing.
To publish locally instead:
pip install build twine
python -m build
twine check dist/*
twine upload dist/*
Acknowledgments
This package leverages implementations from the Irys Python SDK for ANS-104 DataItem format and cryptographic operations. Special thanks to the Irys team for their work on permanent data storage standards.
License
MIT License - see LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file turbo_sdk-0.0.6.tar.gz.
File metadata
- Download URL: turbo_sdk-0.0.6.tar.gz
- Upload date:
- Size: 47.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18ae7f0816e29d9c39253c547a0d2c5f3a479b37688467f6cf96b6ad18f7a17e
|
|
| MD5 |
4f0e43c49b53158969757c8ddbf276d4
|
|
| BLAKE2b-256 |
1ec9ca9e14751788bdcffcca7cabcf806939a0fcdf3c771847183241115cad12
|
Provenance
The following attestation bundles were made for turbo_sdk-0.0.6.tar.gz:
Publisher:
release.yml on ardriveapp/turbo-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
turbo_sdk-0.0.6.tar.gz -
Subject digest:
18ae7f0816e29d9c39253c547a0d2c5f3a479b37688467f6cf96b6ad18f7a17e - Sigstore transparency entry: 1321476833
- Sigstore integration time:
-
Permalink:
ardriveapp/turbo-python-sdk@46ca7ec0a5739118007251eb14c5b3bdef901e95 -
Branch / Tag:
refs/heads/alpha - Owner: https://github.com/ardriveapp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@46ca7ec0a5739118007251eb14c5b3bdef901e95 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file turbo_sdk-0.0.6-py3-none-any.whl.
File metadata
- Download URL: turbo_sdk-0.0.6-py3-none-any.whl
- Upload date:
- Size: 55.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9d3c5c586cd97fecca028c9764e033296730c6bfcead221a29273c9cd9e4f35
|
|
| MD5 |
f47815934ba0023743fc6e316edb95e1
|
|
| BLAKE2b-256 |
7a3f3101f85e81a763b026c26cb38d6d8b70f713fbd649d602bf0ff230f3382d
|
Provenance
The following attestation bundles were made for turbo_sdk-0.0.6-py3-none-any.whl:
Publisher:
release.yml on ardriveapp/turbo-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
turbo_sdk-0.0.6-py3-none-any.whl -
Subject digest:
f9d3c5c586cd97fecca028c9764e033296730c6bfcead221a29273c9cd9e4f35 - Sigstore transparency entry: 1321476907
- Sigstore integration time:
-
Permalink:
ardriveapp/turbo-python-sdk@46ca7ec0a5739118007251eb14c5b3bdef901e95 -
Branch / Tag:
refs/heads/alpha - Owner: https://github.com/ardriveapp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@46ca7ec0a5739118007251eb14c5b3bdef901e95 -
Trigger Event:
workflow_dispatch
-
Statement type: