Mint your DAT in Python
Prerequisites
Python 3.10+ and pip
A funded Pre‑Testnet wallet (for gas)
Credentials:
PRIVATE_KEY – your wallet private key (must start with 0x)
IPFS_JWT – Pinata (or compatible) IPFS JWT
1) Project setup
mkdir lazai-contribution-py
cd lazai-contribution-py
# (recommended) virtual environment
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
2) Install SDK & dependencies
python3 -m pip install -U alith requests rsa eth-account
# optional: if you want to load a .env file instead of exporting vars
# python3 -m pip install python-dotenv
3) Set environment variables
export PRIVATE_KEY=<your wallet private key> # must start with 0x
export IPFS_JWT=<your pinata ipfs jwt>
If you prefer a .env file, install python-dotenv and load it at the top of the script.
4) Create
mint.py
Paste the script:
from alith.lazai import Client, ProofRequest
from alith.data import encrypt
from alith.data.storage import (
PinataIPFS,
UploadOptions,
GetShareLinkOptions,
StorageError,
)
from eth_account.messages import encode_defunct
from os import getenv
import asyncio
import requests
import rsa
import aiohttp
from pydantic import BaseModel
from typing import Optional
class ActualPinataUploadResponse(BaseModel):
id: str
name: str
cid: str
size: int
number_of_files: int
mime_type: str
created_at: str
updated_at: str
network: str
streamable: bool
# Optional fields that might not be present
accept_duplicates: Optional[bool] = None
is_duplicate: Optional[bool] = None
group_id: Optional[str] = None
class CustomPinataIPFS(PinataIPFS):
async def upload(self, opts: UploadOptions):
url = "https://uploads.pinata.cloud/v3/files"
form = aiohttp.FormData()
form.add_field("file", opts.data, filename=opts.name, content_type="text/plain")
form.add_field("network", "public")
headers = {"Authorization": f"Bearer {opts.token}"}
try:
async with self.client.post(url, data=form, headers=headers) as response:
if response.status != 200:
error_text = await response.text()
raise StorageError(f"Pinata IPFS API error: {error_text}")
data = await response.json()
# Use the actual response structure instead of the broken model
pinata_response = ActualPinataUploadResponse(**data["data"])
from alith.data.storage import FileMetadata
return FileMetadata(
id=pinata_response.cid,
name=pinata_response.name,
size=pinata_response.size,
modified_time=pinata_response.updated_at,
)
except aiohttp.ClientError as e:
raise StorageError(f"Network error: {str(e)}") from e
async def main():
client = Client()
ipfs = CustomPinataIPFS() # Use our custom implementation
try:
# 1. Prepare your privacy data and encrypt it
data_file_name = "your_encrypted_data.txt"
privacy_data = "Your Privacy Data"
encryption_seed = "Sign to retrieve your encryption key"
message = encode_defunct(text=encryption_seed)
password = client.wallet.sign_message(message).signature.hex()
encrypted_data = encrypt(privacy_data.encode(), password)
# 2. Upload the privacy data to IPFS and get the shared url
token = getenv("IPFS_JWT", "")
file_meta = await ipfs.upload(
UploadOptions(name=data_file_name, data=encrypted_data, token=token)
)
url = await ipfs.get_share_link(
GetShareLinkOptions(token=token, id=file_meta.id)
)
# 3. Upload the privacy url to LazAI
file_id = client.get_file_id_by_url(url)
if file_id == 0:
file_id = client.add_file(url)
# 4. Request proof in the verified computing node
client.request_proof(file_id, 100)
job_id = client.file_job_ids(file_id)[-1]
job = client.get_job(job_id)
node_info = client.get_node(job[-1])
node_url: str = node_info[1]
pub_key = node_info[-1]
encryption_key = rsa.encrypt(
password.encode(),
rsa.PublicKey.load_pkcs1(pub_key.strip().encode(), format="PEM"),
).hex()
response = requests.post(
f"{node_url}/proof",
json=ProofRequest(
job_id=job_id,
file_id=file_id,
file_url=url,
encryption_key=encryption_key,
encryption_seed=encryption_seed,
proof_url=None,
).model_dump(),
)
if response.status_code == 200:
print("Proof request sent successfully")
else:
print("Failed to send proof request:", response.json())
# 5. Request DAT reward
client.request_reward(file_id)
print("Reward requested for file id", file_id)
except StorageError as e:
print(f"Error: {e}")
except Exception as e:
raise e
finally:
await ipfs.close()
if __name__ == "__main__":
asyncio.run(main())
5) Run
python mint.py
Expected output
Proof request sent successfully
Reward requested for file id <file_id>
Troubleshooting
eth_keys / signing errors → Ensure PRIVATE_KEY starts with 0x and you’re on Python 3.10+.
IPFS 401/403 → Check IPFS_JWT validity and pinning permissions.
Request/connection errors → Re-run after a minute; nodes may be busy. Confirm your RPC/Pre‑Testnet setup on the Quickstart page.
StorageError → Usually indicates bad token or network hiccup; retry the upload step.
Last updated