Zo Passport Python SDK - Phone to Avatar to Passport authentication for Zo World.
Project description
ZoPassport Python SDK
The official Python SDK for Zo World authentication and passport management. Provides seamless integration with the ZoPassport API for phone-based authentication, user profiles, avatar generation, and wallet operations.
✨ Features
- 📱 Phone Authentication - OTP-based authentication with phone numbers
- 🔐 Secure Session Management - Encrypted storage with automatic token refresh
- 👤 User Profile Management - Fetch and update user profiles
- 🎨 Avatar Generation - Generate and manage user avatars
- 💰 Wallet Integration - Check balances and transactions on Base & Avalanche
- 🔄 Automatic Token Refresh - Built-in token refresh with configurable intervals
- 🛡️ Comprehensive Error Handling - Specific exception types for all failure scenarios
- 🔁 Retry Logic - Exponential backoff for failed requests
- 📊 Rate Limit Handling - Automatic rate limit detection and retry-after support
- 🔒 Encrypted Storage - Optional encryption for sensitive data at rest
📦 Installation
Using pip
pip install zopassport
Using uv (recommended for development)
uv add zopassport
Development Installation
git clone https://github.com/ZoHouse/zopassport.git
cd zopassport
pip install -e ".[dev]"
🚀 Quick Start
import asyncio
from zopassport import ZoPassportSDK
async def main():
# Initialize SDK
sdk = ZoPassportSDK(
client_key="YOUR_CLIENT_KEY",
debug=True # Enable debug logging
)
await sdk.initialize()
# Check if already authenticated
if sdk.is_authenticated:
print(f"Welcome back, {sdk.user.first_name}!")
else:
# Step 1: Send OTP
await sdk.auth.send_otp("91", "9876543210")
# Step 2: Verify OTP and login
otp = input("Enter OTP: ")
result = await sdk.login_with_phone("91", "9876543210", otp)
if result["success"]:
print(f"Logged in as {result['user'].first_name}")
# Get wallet balance
balance = await sdk.wallet.get_balance()
print(f"Balance: {balance} $Zo")
# Cleanup
await sdk.close()
if __name__ == "__main__":
asyncio.run(main())
📚 Documentation
Authentication
Send OTP
result = await sdk.auth.send_otp(
country_code="91",
phone_number="9876543210"
)
if result["success"]:
print(result["message"])
Verify OTP and Login
result = await sdk.login_with_phone(
country_code="91",
phone_number="9876543210",
otp="123456"
)
if result["success"]:
user = result["user"]
print(f"Logged in: {user.first_name}")
Check Authentication Status
if sdk.is_authenticated:
print(f"User: {sdk.user.first_name}")
else:
print("Not authenticated")
Logout
await sdk.logout()
Profile Management
Get Profile
token = await sdk.storage.get_item("zo_access_token")
result = await sdk.profile.get_profile(token)
if result["success"]:
profile = result["profile"]
print(f"Bio: {profile.bio}")
Update Profile
token = await sdk.storage.get_item("zo_access_token")
result = await sdk.profile.update_profile(
token,
updates={"bio": "New bio", "first_name": "Jane"}
)
if result["success"]:
print("Profile updated!")
Avatar Generation
Generate Avatar
token = await sdk.storage.get_item("zo_access_token")
result = await sdk.avatar.generate_avatar(token, body_type="bro") # or "bae"
if result["success"]:
task_id = result["task_id"]
print(f"Avatar generation started: {task_id}")
Check Avatar Status
result = await sdk.avatar.get_avatar_status(token, task_id)
if result["status"] == "completed":
print(f"Avatar ready: {result['avatar_url']}")
Poll for Completion
await sdk.avatar.poll_avatar_status(
token,
task_id,
on_progress=lambda status: print(f"Status: {status}"),
on_complete=lambda url: print(f"Avatar: {url}"),
on_error=lambda error: print(f"Error: {error}")
)
Wallet Operations
Get Balance
balance = await sdk.wallet.get_balance()
print(f"Balance: {balance} $Zo")
Get Transactions
result = await sdk.wallet.get_transactions(page=1)
transactions = result["transactions"]
for tx in transactions:
print(tx)
🔧 Configuration
SDK Options
sdk = ZoPassportSDK(
client_key="YOUR_CLIENT_KEY", # Required: API client key
base_url="https://api.io.zo.xyz", # Optional: API base URL
storage_adapter=None, # Optional: Custom storage adapter
auto_refresh=True, # Optional: Enable auto token refresh
refresh_interval=60000, # Optional: Refresh check interval (ms)
debug=False, # Optional: Enable debug logging
max_retries=3, # Optional: Max retry attempts
timeout=10, # Optional: Request timeout (seconds)
)
Storage Adapters
File Storage (Default)
from zopassport import FileStorageAdapter
storage = FileStorageAdapter(file_path="session.json")
sdk = ZoPassportSDK(client_key="...", storage_adapter=storage)
Encrypted File Storage
from zopassport import EncryptedFileStorageAdapter
# Option 1: With password
storage = EncryptedFileStorageAdapter(
file_path="session.enc",
password="your-secure-password"
)
# Option 2: With key file
storage = EncryptedFileStorageAdapter(
file_path="session.enc",
key_file=".session_key"
)
sdk = ZoPassportSDK(client_key="...", storage_adapter=storage)
Memory Storage (Not Persistent)
from zopassport import MemoryStorageAdapter
storage = MemoryStorageAdapter()
sdk = ZoPassportSDK(client_key="...", storage_adapter=storage)
Custom Storage Adapter
from zopassport import StorageAdapter
class CustomStorage(StorageAdapter):
async def get_item(self, key: str) -> Optional[str]:
# Your implementation
pass
async def set_item(self, key: str, value: str) -> None:
# Your implementation
pass
async def remove_item(self, key: str) -> None:
# Your implementation
pass
⚠️ Error Handling
The SDK provides specific exception types for different error scenarios:
from zopassport import (
ZoPassportError, # Base exception
ZoAuthenticationError, # Authentication failures
ZoNetworkError, # Network issues
ZoRateLimitError, # Rate limiting
ZoValidationError, # Invalid input
ZoStorageError, # Storage failures
ZoWalletError, # Wallet operations
)
try:
await sdk.login_with_phone("91", "9876543210", "123456")
except ZoAuthenticationError as e:
print(f"Auth failed: {e}")
except ZoRateLimitError as e:
print(f"Rate limited, retry after {e.retry_after}s")
except ZoNetworkError as e:
print(f"Network error: {e}")
except ZoPassportError as e:
print(f"SDK error: {e}")
🔒 Security Best Practices
1. Use Encrypted Storage
# Use password-based encryption
storage = EncryptedFileStorageAdapter(
file_path="session.enc",
password=os.environ["SESSION_PASSWORD"]
)
2. Store Client Key Securely
# Never hardcode credentials
client_key = os.environ.get("ZO_CLIENT_KEY")
sdk = ZoPassportSDK(client_key=client_key)
3. Handle Sensitive Data Carefully
# Don't log sensitive information
logger.setLevel("INFO") # Avoid DEBUG in production
4. Implement Proper Session Management
# Always close SDK when done
try:
# Your code
pass
finally:
await sdk.close()
5. Validate User Input
# Validate before sending to API
if not phone_number.isdigit():
raise ValueError("Invalid phone number")
🧪 Testing
Run Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=src/zopassport --cov-report=html
# Run specific test file
pytest tests/unit/test_auth.py
# Run with verbose output
pytest -v
Run Linting
# Format code
black src/ tests/
# Lint code
ruff check src/ tests/
# Type check
mypy src/
🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
Development Setup
# Clone repository
git clone https://github.com/ZoHouse/zopassport.git
cd zopassport
# Install dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
# Run tests
pytest
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
💬 Support
- Create an issue on GitHub
- Email: dev@zo.xyz
- Discord: Zo World Community
🙏 Acknowledgments
Built with ❤️ by the Zo World Team
Note: This SDK requires Python 3.11 or higher.
Project details
Release history Release notifications | RSS feed
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 zopassport-0.1.0.tar.gz.
File metadata
- Download URL: zopassport-0.1.0.tar.gz
- Upload date:
- Size: 130.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13b77ce3ff77b9c89d55b09a16d8444fc22172634b6658b4b097aa6f92d8d55e
|
|
| MD5 |
cef1f33dc064354ff5f6409677e889cf
|
|
| BLAKE2b-256 |
01b9d401bd860717af64e7f685e65500acdbb925586cac57a0505c6f1e8adb36
|
Provenance
The following attestation bundles were made for zopassport-0.1.0.tar.gz:
Publisher:
publish.yml on ZoHouse/zopassport-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zopassport-0.1.0.tar.gz -
Subject digest:
13b77ce3ff77b9c89d55b09a16d8444fc22172634b6658b4b097aa6f92d8d55e - Sigstore transparency entry: 783823564
- Sigstore integration time:
-
Permalink:
ZoHouse/zopassport-py@3e89b58ca83e4a20b9d79c0c4fdf041b98dc5e56 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ZoHouse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e89b58ca83e4a20b9d79c0c4fdf041b98dc5e56 -
Trigger Event:
release
-
Statement type:
File details
Details for the file zopassport-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zopassport-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
443168637cdd34175cd6b592b186e53f528709f8e3b3d59c181ad04e47ee57b0
|
|
| MD5 |
fde63a6457b73b4d435b42513ec10490
|
|
| BLAKE2b-256 |
2b20aca091ee5bfdc7e0497d30f5ab0ff3dfa95428f3c02567732207b57f3d3e
|
Provenance
The following attestation bundles were made for zopassport-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ZoHouse/zopassport-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zopassport-0.1.0-py3-none-any.whl -
Subject digest:
443168637cdd34175cd6b592b186e53f528709f8e3b3d59c181ad04e47ee57b0 - Sigstore transparency entry: 783823622
- Sigstore integration time:
-
Permalink:
ZoHouse/zopassport-py@3e89b58ca83e4a20b9d79c0c4fdf041b98dc5e56 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ZoHouse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3e89b58ca83e4a20b9d79c0c4fdf041b98dc5e56 -
Trigger Event:
release
-
Statement type: