0g-inference-sdk 0.2.0__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.
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/PKG-INFO +1115 -0
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/SOURCES.txt +36 -0
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/dependency_links.txt +1 -0
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/not-zip-safe +1 -0
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/requires.txt +13 -0
- 0g_inference_sdk-0.2.0/0g_inference_sdk.egg-info/top_level.txt +1 -0
- 0g_inference_sdk-0.2.0/LICENSE +21 -0
- 0g_inference_sdk-0.2.0/MANIFEST.in +6 -0
- 0g_inference_sdk-0.2.0/PKG-INFO +1115 -0
- 0g_inference_sdk-0.2.0/README.md +1064 -0
- 0g_inference_sdk-0.2.0/requirements.txt +11 -0
- 0g_inference_sdk-0.2.0/setup.cfg +4 -0
- 0g_inference_sdk-0.2.0/setup.py +63 -0
- 0g_inference_sdk-0.2.0/tests/test_crypto.py +297 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/__init__.py +185 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/auth.py +276 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/broker.py +285 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/cache.py +343 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/constants.py +160 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/contracts/__init__.py +25 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/contracts/abis.py +94 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/__init__.py +87 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/babyjub.py +294 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/eddsa.py +283 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/field.py +93 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/pedersen.py +180 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/crypto/pedersen_bases.py +135 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/exceptions.py +156 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/extractors.py +295 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/inference.py +797 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/ledger.py +464 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/models.py +274 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/py.typed +0 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/read_only.py +315 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/session.py +338 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/setup.py +63 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/utils.py +146 -0
- 0g_inference_sdk-0.2.0/zerog_py_sdk/verifier.py +291 -0
|
@@ -0,0 +1,1115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: 0g-inference-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for the 0G Compute Network - AI inference services on decentralized infrastructure
|
|
5
|
+
Home-page: https://github.com/mandatedisrael/0g-py-sdk
|
|
6
|
+
Author: notMartin
|
|
7
|
+
Author-email: damiclone@example.com
|
|
8
|
+
Project-URL: Documentation, https://docs.0g.ai/developer-hub/building-on-0g/compute-network/sdk
|
|
9
|
+
Project-URL: Source, https://github.com/mandatedisrael/0g-py-sdk
|
|
10
|
+
Project-URL: Bug Reports, https://github.com/mandatedisrael/0g-py-sdk/issues
|
|
11
|
+
Keywords: 0g blockchain ai inference decentralized llm crypto web3
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: web3>=6.0.0
|
|
27
|
+
Requires-Dist: eth-account>=0.10.0
|
|
28
|
+
Requires-Dist: eth-utils>=2.0.0
|
|
29
|
+
Requires-Dist: requests>=2.31.0
|
|
30
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
31
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Dynamic: author
|
|
39
|
+
Dynamic: author-email
|
|
40
|
+
Dynamic: classifier
|
|
41
|
+
Dynamic: description
|
|
42
|
+
Dynamic: description-content-type
|
|
43
|
+
Dynamic: home-page
|
|
44
|
+
Dynamic: keywords
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
Dynamic: project-url
|
|
47
|
+
Dynamic: provides-extra
|
|
48
|
+
Dynamic: requires-dist
|
|
49
|
+
Dynamic: requires-python
|
|
50
|
+
Dynamic: summary
|
|
51
|
+
|
|
52
|
+
# 0G Compute Network Python SDK
|
|
53
|
+
|
|
54
|
+
[](https://www.python.org/downloads/)
|
|
55
|
+
[](https://opensource.org/licenses/MIT)
|
|
56
|
+
|
|
57
|
+
Python SDK for interacting with the 0G Compute Network - a decentralized AI inference marketplace where you pay for AI model access using blockchain tokens.
|
|
58
|
+
|
|
59
|
+
> **✅ Available on PyPI:** `pip install 0g-py-sdk`
|
|
60
|
+
|
|
61
|
+
## What is 0G Compute Network?
|
|
62
|
+
|
|
63
|
+
0G Compute Network is a **blockchain-based marketplace** for AI inference services:
|
|
64
|
+
- **Providers** offer AI models (LLMs) with TEE-verified compute
|
|
65
|
+
- **Users** pay per request using 0G tokens (ERC-20)
|
|
66
|
+
- **Smart contracts** handle billing, accounts, and cryptographic verification
|
|
67
|
+
- **Decentralized** - no central authority, fully on-chain payment settlement
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- ✅ **Session Token Auth**: New simplified authorization system (no complex headers)
|
|
72
|
+
- ✅ **Account Management**: Fund and manage prepaid accounts for AI services
|
|
73
|
+
- ✅ **Service Discovery**: List and query available AI providers on-chain
|
|
74
|
+
- ✅ **Read-Only Mode**: Browse services without wallet connection
|
|
75
|
+
- ✅ **Multi-Network Support**: Mainnet and testnet with auto-detection
|
|
76
|
+
- ✅ **API Key Management**: Create persistent, revocable API keys
|
|
77
|
+
- ✅ **Provider Integration**: OpenAI-compatible API interface
|
|
78
|
+
- ✅ **Verifiable Computing**: TEE (Trusted Execution Environment) attestation support
|
|
79
|
+
- ✅ **Response Verification**: Verify TEE-signed responses
|
|
80
|
+
- ✅ **Caching System**: Built-in caching for performance
|
|
81
|
+
|
|
82
|
+
## How It Works
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|
86
|
+
│ Your App │ │ 0G Network │ │ AI Provider│
|
|
87
|
+
│ (Python) │ │ (Blockchain) │ │ (TEE) │
|
|
88
|
+
└──────┬──────┘ └──────┬───────┘ └──────┬──────┘
|
|
89
|
+
│ │ │
|
|
90
|
+
│ 1. Fund account │ │
|
|
91
|
+
├───────────────────────────────>│ │
|
|
92
|
+
│ (deposit 0G tokens) │ │
|
|
93
|
+
│ │ │
|
|
94
|
+
│ 2. Acknowledge provider │ │
|
|
95
|
+
├───────────────────────────────>│<───────────────────────────────┤
|
|
96
|
+
│ (verify TEE signer) │ (get TEE attestation) │
|
|
97
|
+
│ │ │
|
|
98
|
+
│ 3. Get session token │ │
|
|
99
|
+
│ (auto-generated & cached) │ │
|
|
100
|
+
│ │ │
|
|
101
|
+
│ 4. Make inference request │ │
|
|
102
|
+
├────────────────────────────────┼───────────────────────────────>│
|
|
103
|
+
│ (with Authorization header) │ │
|
|
104
|
+
│ │ │
|
|
105
|
+
│ 5. Get AI response │ │
|
|
106
|
+
│<────────────────────────────────────────────────────────────────┤
|
|
107
|
+
│ │ │
|
|
108
|
+
│ 6. Provider settles billing │ │
|
|
109
|
+
│ │<───────────────────────────────┤
|
|
110
|
+
│ │ (deduct tokens on-chain) │
|
|
111
|
+
└────────────────────────────────┴────────────────────────────────┘
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## System Requirements
|
|
115
|
+
|
|
116
|
+
- **Python**: 3.8 or higher
|
|
117
|
+
|
|
118
|
+
## Installation
|
|
119
|
+
|
|
120
|
+
> **Quick Start:** For a condensed setup guide, see [SETUP.md](SETUP.md)
|
|
121
|
+
|
|
122
|
+
### Install from PyPI (Recommended)
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install 0g-py-sdk
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Development Setup (Optional)
|
|
129
|
+
|
|
130
|
+
If you want to contribute or modify the SDK:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Clone the repository
|
|
134
|
+
git clone https://github.com/mandatedisrael/0g-py-sdk.git
|
|
135
|
+
cd 0g-py-sdk/0g_py_inference
|
|
136
|
+
|
|
137
|
+
# Create virtual environment
|
|
138
|
+
python3 -m venv venv
|
|
139
|
+
source venv/bin/activate # macOS/Linux
|
|
140
|
+
# OR
|
|
141
|
+
venv\Scripts\activate # Windows
|
|
142
|
+
|
|
143
|
+
# Install in development mode
|
|
144
|
+
pip install -e .
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Configure Environment Variables
|
|
148
|
+
|
|
149
|
+
Create a `.env` file in your project directory:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
PRIVATE_KEY=your_private_key_without_0x_prefix
|
|
153
|
+
RPC_URL=https://evmrpc-testnet.0g.ai
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**⚠️ Important:** Never commit your `.env` file to version control!
|
|
157
|
+
|
|
158
|
+
## Quick Start
|
|
159
|
+
|
|
160
|
+
After following the installation steps, create a script or use the provided `test.py`:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from zerog_py_sdk import create_broker
|
|
164
|
+
from zerog_py_sdk.utils import og_to_wei
|
|
165
|
+
import requests
|
|
166
|
+
import json
|
|
167
|
+
import os
|
|
168
|
+
from dotenv import load_dotenv
|
|
169
|
+
|
|
170
|
+
# Load environment variables from .env file
|
|
171
|
+
load_dotenv()
|
|
172
|
+
|
|
173
|
+
# 1. Initialize broker with your private key
|
|
174
|
+
broker = create_broker(
|
|
175
|
+
private_key=os.getenv('PRIVATE_KEY'),
|
|
176
|
+
rpc_url=os.getenv('RPC_URL', 'https://evmrpc-testnet.0g.ai')
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# 2. Discover available AI services
|
|
180
|
+
services = broker.inference.list_service()
|
|
181
|
+
provider_address = services[0].provider
|
|
182
|
+
|
|
183
|
+
print(f"Provider: {provider_address}")
|
|
184
|
+
print(f"Model: {services[0].model}")
|
|
185
|
+
|
|
186
|
+
# 3. Fund your account (one-time setup)
|
|
187
|
+
# Skip if you already have funds
|
|
188
|
+
account = broker.ledger.get_ledger()
|
|
189
|
+
if account.balance < 0.1:
|
|
190
|
+
broker.ledger.deposit_fund("2") # Add 2 OG tokens
|
|
191
|
+
print(f"✓ Added funds. New balance: {broker.ledger.get_ledger().balance} OG")
|
|
192
|
+
|
|
193
|
+
# 4. Acknowledge provider (one-time per provider)
|
|
194
|
+
broker.inference.acknowledge_provider_signer(provider_address)
|
|
195
|
+
print("✓ Provider acknowledged")
|
|
196
|
+
|
|
197
|
+
# 5. Transfer funds to provider sub-account
|
|
198
|
+
broker.ledger.transfer_fund(provider_address, "inference", og_to_wei("0.5"))
|
|
199
|
+
print("✓ Transferred 0.5 OG to provider")
|
|
200
|
+
|
|
201
|
+
# 6. Get service metadata
|
|
202
|
+
metadata = broker.inference.get_service_metadata(provider_address)
|
|
203
|
+
endpoint = metadata['endpoint'] # Automatically appends /v1/proxy
|
|
204
|
+
model = metadata['model']
|
|
205
|
+
|
|
206
|
+
# 7. Get authentication headers (NEW: simplified session token auth)
|
|
207
|
+
headers = broker.inference.get_request_headers(provider_address)
|
|
208
|
+
# Returns: {"Authorization": "Bearer app-sk-..."}
|
|
209
|
+
|
|
210
|
+
# 8. Make inference request
|
|
211
|
+
messages = [{"role": "user", "content": "What is 2+2?"}]
|
|
212
|
+
response = requests.post(
|
|
213
|
+
f"{endpoint}/chat/completions",
|
|
214
|
+
headers={"Content-Type": "application/json", **headers},
|
|
215
|
+
json={"messages": messages, "model": model}
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# 9. Get the answer
|
|
219
|
+
if response.status_code == 200:
|
|
220
|
+
answer = response.json()['choices'][0]['message']['content']
|
|
221
|
+
print(f"Answer: {answer}")
|
|
222
|
+
else:
|
|
223
|
+
print(f"Error: {response.status_code} - {response.text}")
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Output:**
|
|
227
|
+
```
|
|
228
|
+
Provider: 0xf07240Efa67755B5311bc75784a061eDB47165Dd
|
|
229
|
+
Model: qwen/qwen-2.5-7b-instruct
|
|
230
|
+
✓ Added funds. New balance: 2.0 OG
|
|
231
|
+
✓ Provider acknowledged
|
|
232
|
+
✓ Transferred 0.5 OG to provider
|
|
233
|
+
Answer: 2 + 2 = 4.
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Browse Services Without Wallet (Read-Only Mode)
|
|
239
|
+
|
|
240
|
+
You can list available AI providers without connecting a wallet:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from zerog_py_sdk import create_read_only_broker
|
|
244
|
+
|
|
245
|
+
# Create read-only broker (no private key needed)
|
|
246
|
+
broker = create_read_only_broker()
|
|
247
|
+
|
|
248
|
+
# List all available services
|
|
249
|
+
services = broker.list_service()
|
|
250
|
+
for svc in services:
|
|
251
|
+
print(f"{svc.model} - {svc.provider}")
|
|
252
|
+
print(f" URL: {svc.url}")
|
|
253
|
+
print(f" Input: {svc.input_price} wei/token")
|
|
254
|
+
print(f" Output: {svc.output_price} wei/token")
|
|
255
|
+
|
|
256
|
+
# Get services with health metrics
|
|
257
|
+
detailed = broker.list_service_with_detail()
|
|
258
|
+
for svc in detailed:
|
|
259
|
+
if svc.health_metrics:
|
|
260
|
+
print(f"{svc.model}: {svc.health_metrics.uptime}% uptime")
|
|
261
|
+
|
|
262
|
+
# Use mainnet instead of testnet
|
|
263
|
+
mainnet_broker = create_read_only_broker(network="mainnet")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Network Configuration
|
|
269
|
+
|
|
270
|
+
The SDK supports multiple networks with auto-detection:
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from zerog_py_sdk import (
|
|
274
|
+
create_broker,
|
|
275
|
+
get_contract_addresses,
|
|
276
|
+
get_rpc_url,
|
|
277
|
+
MAINNET_CHAIN_ID, # 16661
|
|
278
|
+
TESTNET_CHAIN_ID, # 16602
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Testnet (default)
|
|
282
|
+
broker = create_broker(
|
|
283
|
+
private_key="0x...",
|
|
284
|
+
rpc_url="https://evmrpc-testnet.0g.ai"
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Mainnet
|
|
288
|
+
broker = create_broker(
|
|
289
|
+
private_key="0x...",
|
|
290
|
+
rpc_url="https://evmrpc.0g.ai"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# Get contract addresses for a network
|
|
294
|
+
addrs = get_contract_addresses("mainnet")
|
|
295
|
+
print(f"Inference: {addrs.inference}")
|
|
296
|
+
print(f"Ledger: {addrs.ledger}")
|
|
297
|
+
|
|
298
|
+
# Auto-detect from chain ID
|
|
299
|
+
addrs = get_contract_addresses(chain_id=16661)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## SDK Architecture
|
|
303
|
+
|
|
304
|
+
### High-Level Structure
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
zerog_py_sdk/
|
|
308
|
+
├── broker.py # Main entry point - ZGServingBroker class
|
|
309
|
+
├── ledger.py # Account & balance management (LedgerManager)
|
|
310
|
+
├── inference.py # Service discovery & request signing (InferenceManager)
|
|
311
|
+
├── session.py # Session token management (NEW)
|
|
312
|
+
├── read_only.py # Read-only broker for wallet-less operations (NEW)
|
|
313
|
+
├── constants.py # Network constants & contract addresses (NEW)
|
|
314
|
+
├── extractors.py # Service type extractors (chatbot, image, etc.) (NEW)
|
|
315
|
+
├── cache.py # Built-in caching system (NEW)
|
|
316
|
+
├── verifier.py # Response verification for TEE (NEW)
|
|
317
|
+
├── auth.py # Cryptographic operations (native Python)
|
|
318
|
+
├── models.py # Data structures (ServiceMetadata, LedgerAccount, etc.)
|
|
319
|
+
├── exceptions.py # Custom error types
|
|
320
|
+
├── utils.py # Helper functions (og_to_wei, parse receipts, etc.)
|
|
321
|
+
└── crypto/ # Native Python crypto (no Node.js dependency)
|
|
322
|
+
├── eddsa.py # EdDSA signatures on Baby JubJub curve
|
|
323
|
+
├── pedersen.py # Pedersen hash function
|
|
324
|
+
└── baby_jubjub.py # Baby JubJub elliptic curve
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Component Breakdown
|
|
328
|
+
|
|
329
|
+
#### 1. **Broker** (`broker.py`)
|
|
330
|
+
|
|
331
|
+
The main orchestrator that initializes and connects all components.
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
class ZGServingBroker:
|
|
335
|
+
"""
|
|
336
|
+
Main broker class that coordinates:
|
|
337
|
+
- Blockchain connection (Web3)
|
|
338
|
+
- Smart contract instances
|
|
339
|
+
- Ledger operations
|
|
340
|
+
- Inference operations
|
|
341
|
+
"""
|
|
342
|
+
|
|
343
|
+
def __init__(self, private_key, rpc_url, contract_address):
|
|
344
|
+
self.web3 = Web3(HTTPProvider(rpc_url))
|
|
345
|
+
self.account = Account.from_key(private_key)
|
|
346
|
+
|
|
347
|
+
# Initialize smart contracts
|
|
348
|
+
self.ledger_contract = self._load_contract("LedgerManager")
|
|
349
|
+
self.inference_contract = self._load_contract("InferenceServing")
|
|
350
|
+
|
|
351
|
+
# Initialize managers
|
|
352
|
+
self.ledger = LedgerManager(...) # For payments
|
|
353
|
+
self.inference = InferenceManager(...) # For AI requests
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Key methods:**
|
|
357
|
+
- `create_broker(private_key, rpc_url)` - Factory function
|
|
358
|
+
- `create_broker_from_env()` - Load from .env file
|
|
359
|
+
- `get_address()` - Get your wallet address
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
#### 2. **LedgerManager** (`ledger.py`)
|
|
364
|
+
|
|
365
|
+
Handles all on-chain account and payment operations.
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
class LedgerManager:
|
|
369
|
+
"""
|
|
370
|
+
Manages your prepaid account on the blockchain.
|
|
371
|
+
Think of it as your "wallet" for AI services.
|
|
372
|
+
"""
|
|
373
|
+
|
|
374
|
+
def add_ledger(amount: str):
|
|
375
|
+
"""
|
|
376
|
+
Create account or add funds to main ledger.
|
|
377
|
+
Sends 0G tokens to smart contract.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
amount: OG tokens (e.g., "0.1")
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
def deposit_fund(amount: str):
|
|
384
|
+
"""
|
|
385
|
+
Add more funds to existing account.
|
|
386
|
+
"""
|
|
387
|
+
|
|
388
|
+
def transfer_fund(provider_address, service_type, amount_wei):
|
|
389
|
+
"""
|
|
390
|
+
Allocate funds to specific provider's sub-account.
|
|
391
|
+
Must be done before making inference requests.
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
def get_ledger() -> LedgerAccount:
|
|
395
|
+
"""
|
|
396
|
+
Check your balance.
|
|
397
|
+
Returns: balance, locked, total_balance (in OG)
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
def retrieve_fund(service_type):
|
|
401
|
+
"""
|
|
402
|
+
Withdraw unused funds from provider sub-accounts.
|
|
403
|
+
"""
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**Account Model:**
|
|
407
|
+
```
|
|
408
|
+
Main Ledger (Your Account)
|
|
409
|
+
├── Available Balance: 2.0 OG
|
|
410
|
+
├── Locked Balance: 0.5 OG (allocated to providers)
|
|
411
|
+
└── Total Balance: 2.5 OG
|
|
412
|
+
|
|
413
|
+
Provider Sub-Accounts
|
|
414
|
+
├── Provider A: 0.3 OG (for inference)
|
|
415
|
+
└── Provider B: 0.2 OG (for inference)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
#### 3. **InferenceManager** (`inference.py`)
|
|
421
|
+
|
|
422
|
+
Discovers AI services and generates authenticated request headers.
|
|
423
|
+
|
|
424
|
+
```python
|
|
425
|
+
class InferenceManager:
|
|
426
|
+
"""
|
|
427
|
+
Handles AI inference operations:
|
|
428
|
+
- Finding available providers
|
|
429
|
+
- Verifying TEE attestations
|
|
430
|
+
- Generating session tokens for authentication
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
def list_service() -> List[ServiceMetadata]:
|
|
434
|
+
"""
|
|
435
|
+
Query blockchain for all registered AI providers.
|
|
436
|
+
Returns list of available models with pricing.
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
def get_service(provider_address) -> ServiceMetadata:
|
|
440
|
+
"""
|
|
441
|
+
Get specific provider's service details.
|
|
442
|
+
"""
|
|
443
|
+
|
|
444
|
+
def acknowledge_provider_signer(provider_address):
|
|
445
|
+
"""
|
|
446
|
+
One-time setup per provider:
|
|
447
|
+
1. Gets TEE attestation from provider
|
|
448
|
+
2. Verifies quote (optional)
|
|
449
|
+
3. Records TEE signer on-chain
|
|
450
|
+
|
|
451
|
+
This links the provider's TEE to their blockchain address.
|
|
452
|
+
"""
|
|
453
|
+
|
|
454
|
+
def get_service_metadata(provider_address) -> dict:
|
|
455
|
+
"""
|
|
456
|
+
Get inference endpoint and model name.
|
|
457
|
+
Automatically appends /v1/proxy to URL.
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
{
|
|
461
|
+
"endpoint": "http://provider.com:8080/v1/proxy",
|
|
462
|
+
"model": "qwen/qwen-2.5-7b-instruct"
|
|
463
|
+
}
|
|
464
|
+
"""
|
|
465
|
+
|
|
466
|
+
def get_request_headers(provider_address) -> dict:
|
|
467
|
+
"""
|
|
468
|
+
Generate session token auth headers for request.
|
|
469
|
+
|
|
470
|
+
NEW: No content parameter needed! Session tokens are
|
|
471
|
+
provider-scoped and auto-cached for 24 hours.
|
|
472
|
+
|
|
473
|
+
Returns headers like:
|
|
474
|
+
{
|
|
475
|
+
"Authorization": "Bearer app-sk-..."
|
|
476
|
+
}
|
|
477
|
+
"""
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Service Discovery Flow:**
|
|
481
|
+
```python
|
|
482
|
+
# 1. List all services
|
|
483
|
+
services = broker.inference.list_service()
|
|
484
|
+
# Returns: [ServiceMetadata, ServiceMetadata, ...]
|
|
485
|
+
|
|
486
|
+
# 2. ServiceMetadata object contains:
|
|
487
|
+
service = services[0]
|
|
488
|
+
service.provider # "0xf07240..."
|
|
489
|
+
service.model # "qwen/qwen-2.5-7b-instruct"
|
|
490
|
+
service.url # "http://50.145.48.92:30081"
|
|
491
|
+
service.input_price # 100000000000 (wei per token)
|
|
492
|
+
service.output_price # 400000000000 (wei per token)
|
|
493
|
+
service.verifiability # "TeeML"
|
|
494
|
+
service.is_verifiable() # True
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
#### 4. **SessionManager** (`session.py`) - NEW
|
|
500
|
+
|
|
501
|
+
Manages session tokens for the new authorization system.
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
from zerog_py_sdk import SessionManager, SessionMode
|
|
505
|
+
|
|
506
|
+
class SessionManager:
|
|
507
|
+
"""
|
|
508
|
+
Manages session tokens for the 0G Compute Network.
|
|
509
|
+
|
|
510
|
+
Replaces the old header-based authentication with the new
|
|
511
|
+
session token system. Supports both ephemeral (SDK usage)
|
|
512
|
+
and persistent (API keys) tokens.
|
|
513
|
+
"""
|
|
514
|
+
|
|
515
|
+
def get_request_headers(provider_address) -> dict:
|
|
516
|
+
"""
|
|
517
|
+
Get request headers with session token authorization.
|
|
518
|
+
Auto-generates and caches ephemeral tokens (24h).
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
{"Authorization": "Bearer app-sk-..."}
|
|
522
|
+
"""
|
|
523
|
+
|
|
524
|
+
def create_api_key(provider_address, expires_in=None) -> ApiKeyInfo:
|
|
525
|
+
"""
|
|
526
|
+
Create a persistent API key (tokenId 0-254).
|
|
527
|
+
Can be individually revoked. Great for server applications.
|
|
528
|
+
|
|
529
|
+
Args:
|
|
530
|
+
provider_address: Provider's wallet address
|
|
531
|
+
expires_in: Expiration in milliseconds (0 = never)
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
ApiKeyInfo with raw_token for use in requests
|
|
535
|
+
"""
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**Token Types:**
|
|
539
|
+
- **Ephemeral (tokenId=255)**: Auto-generated, 24h max, can't be individually revoked
|
|
540
|
+
- **Persistent (tokenId 0-254)**: Manually created, individually revocable API keys
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
#### 5. **Native Crypto** (`crypto/`) - No Node.js Required!
|
|
545
|
+
|
|
546
|
+
The SDK now includes pure Python implementations of ZK-friendly cryptography:
|
|
547
|
+
|
|
548
|
+
```python
|
|
549
|
+
# Internally used - you don't need to call these directly
|
|
550
|
+
from zerog_py_sdk.crypto import (
|
|
551
|
+
eddsa_sign, # EdDSA signatures on Baby JubJub
|
|
552
|
+
pedersen_hash, # Pedersen hash function
|
|
553
|
+
BabyJubJubPoint, # Baby JubJub curve operations
|
|
554
|
+
)
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**Why native Python?**
|
|
558
|
+
- No Node.js/npm dependency
|
|
559
|
+
- Easier installation
|
|
560
|
+
- Works in any Python environment
|
|
561
|
+
- Same cryptographic guarantees as TypeScript SDK
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
#### 6. **Models** (`models.py`)
|
|
566
|
+
|
|
567
|
+
Data structures for type safety.
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
@dataclass
|
|
571
|
+
class ServiceMetadata:
|
|
572
|
+
provider: str # Wallet address
|
|
573
|
+
service_type: str # "chatbot"
|
|
574
|
+
url: str # Provider endpoint
|
|
575
|
+
input_price: int # Wei per input token
|
|
576
|
+
output_price: int # Wei per output token
|
|
577
|
+
updated_at: int # Timestamp
|
|
578
|
+
model: str # Model identifier
|
|
579
|
+
verifiability: str # "TeeML"
|
|
580
|
+
|
|
581
|
+
@dataclass
|
|
582
|
+
class LedgerAccount:
|
|
583
|
+
balance: float # Available OG
|
|
584
|
+
locked: float # Locked in provider accounts
|
|
585
|
+
total_balance: float # balance + locked
|
|
586
|
+
|
|
587
|
+
@dataclass
|
|
588
|
+
class RequestHeaders:
|
|
589
|
+
# Cryptographic auth headers for inference
|
|
590
|
+
...
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
#### 7. **Utilities** (`utils.py`)
|
|
596
|
+
|
|
597
|
+
Helper functions for common operations.
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
def og_to_wei(amount: str) -> int:
|
|
601
|
+
"""Convert OG tokens to wei (10^18)"""
|
|
602
|
+
return int(float(amount) * 10**18)
|
|
603
|
+
|
|
604
|
+
def wei_to_og(wei: int) -> float:
|
|
605
|
+
"""Convert wei to OG tokens"""
|
|
606
|
+
return wei / 10**18
|
|
607
|
+
|
|
608
|
+
def parse_transaction_receipt(receipt):
|
|
609
|
+
"""Extract useful info from blockchain receipt"""
|
|
610
|
+
return {
|
|
611
|
+
"transaction_hash": receipt.transactionHash.hex(),
|
|
612
|
+
"block_number": receipt.blockNumber,
|
|
613
|
+
"gas_used": receipt.gasUsed,
|
|
614
|
+
"status": receipt.status
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
### Request Flow (Detailed)
|
|
621
|
+
|
|
622
|
+
Here's what happens when you make an inference request with the new session token system:
|
|
623
|
+
|
|
624
|
+
```python
|
|
625
|
+
# Step 1: Get session token headers
|
|
626
|
+
headers = broker.inference.get_request_headers(provider)
|
|
627
|
+
# Returns: {"Authorization": "Bearer app-sk-..."}
|
|
628
|
+
|
|
629
|
+
# Internally:
|
|
630
|
+
# 1.1: Check session cache for valid token
|
|
631
|
+
cached = session_cache.get(provider)
|
|
632
|
+
if cached and cached.expires_at > now + 1_hour:
|
|
633
|
+
return cached.headers
|
|
634
|
+
|
|
635
|
+
# 1.2: Create session token
|
|
636
|
+
token = {
|
|
637
|
+
"address": user_address,
|
|
638
|
+
"provider": provider,
|
|
639
|
+
"timestamp": current_time_ms,
|
|
640
|
+
"expiresAt": current_time_ms + 24_hours,
|
|
641
|
+
"nonce": random_hex(16),
|
|
642
|
+
"generation": account.generation,
|
|
643
|
+
"tokenId": 255 # Ephemeral
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
# 1.3: Sign token (native Python EdDSA)
|
|
647
|
+
message_hash = keccak256(json.dumps(token))
|
|
648
|
+
signature = eth_sign(private_key, message_hash)
|
|
649
|
+
|
|
650
|
+
# 1.4: Encode as Authorization header
|
|
651
|
+
encoded = base64(json.dumps(token) + "|" + signature)
|
|
652
|
+
return {"Authorization": f"Bearer app-sk-{encoded}"}
|
|
653
|
+
|
|
654
|
+
# Step 2: Make HTTP request to provider
|
|
655
|
+
response = requests.post(
|
|
656
|
+
f"{endpoint}/chat/completions",
|
|
657
|
+
headers={"Content-Type": "application/json", **headers},
|
|
658
|
+
json={"messages": [...], "model": model}
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
# Step 3: Provider validates session token
|
|
662
|
+
# Provider checks:
|
|
663
|
+
# ✓ Signature matches address in token
|
|
664
|
+
# ✓ Token not expired
|
|
665
|
+
# ✓ Token generation matches account (not batch-revoked)
|
|
666
|
+
# ✓ TokenId not individually revoked (for persistent tokens)
|
|
667
|
+
# ✓ User has balance in contract
|
|
668
|
+
|
|
669
|
+
# Step 4: Provider processes request
|
|
670
|
+
# ✓ Runs LLM inference
|
|
671
|
+
# ✓ Returns response
|
|
672
|
+
|
|
673
|
+
# Step 5: Provider settles billing (async)
|
|
674
|
+
# ✓ Calls contract.settleAccounts([user_address])
|
|
675
|
+
# ✓ Deducts actual tokens used from user balance
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
## Complete Working Example
|
|
681
|
+
|
|
682
|
+
See `test.py` for a full working example that:
|
|
683
|
+
|
|
684
|
+
1. ✅ Initializes broker
|
|
685
|
+
2. ✅ Discovers providers
|
|
686
|
+
3. ✅ Checks & adds funds
|
|
687
|
+
4. ✅ Acknowledges provider
|
|
688
|
+
5. ✅ Transfers funds to provider
|
|
689
|
+
6. ✅ Makes inference request
|
|
690
|
+
7. ✅ Receives AI response
|
|
691
|
+
|
|
692
|
+
Run it:
|
|
693
|
+
```bash
|
|
694
|
+
# Make sure you're in the project directory
|
|
695
|
+
cd og-py-sdk
|
|
696
|
+
|
|
697
|
+
# Activate virtual environment
|
|
698
|
+
source venv/bin/activate
|
|
699
|
+
|
|
700
|
+
# Run the test
|
|
701
|
+
python3 test.py
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Expected output:**
|
|
705
|
+
```
|
|
706
|
+
Testing broker initialization...
|
|
707
|
+
✓ Broker initialized
|
|
708
|
+
✓ Address: 0xB3AD3a10d187cbc4ca3e8c3EDED62F8286F8e16E
|
|
709
|
+
|
|
710
|
+
Testing service discovery...
|
|
711
|
+
✓ Found 4 services
|
|
712
|
+
|
|
713
|
+
Querying provider for 'Highest World Cup Holder'...
|
|
714
|
+
✓ Using provider: 0xf07240Efa67755B5311bc75784a061eDB47165Dd
|
|
715
|
+
✓ Model: phala/gpt-oss-120b
|
|
716
|
+
✓ Main ledger balance: 2.0 OG
|
|
717
|
+
✓ Provider acknowledged
|
|
718
|
+
✓ Transferred funds
|
|
719
|
+
|
|
720
|
+
==================================================
|
|
721
|
+
Question: Who owns the largest number of football World Cups?
|
|
722
|
+
Answer: Brazil owns the largest number of football World Cups with 5 titles.
|
|
723
|
+
==================================================
|
|
724
|
+
|
|
725
|
+
✅ All tests passed!
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## API Reference
|
|
731
|
+
|
|
732
|
+
### Broker Initialization
|
|
733
|
+
|
|
734
|
+
```python
|
|
735
|
+
from zerog_py_sdk import create_broker
|
|
736
|
+
|
|
737
|
+
broker = create_broker(
|
|
738
|
+
private_key="0x...",
|
|
739
|
+
rpc_url="https://evmrpc-testnet.0g.ai",
|
|
740
|
+
contract_address=None # Optional, uses default if not provided
|
|
741
|
+
)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### Ledger Operations
|
|
745
|
+
|
|
746
|
+
```python
|
|
747
|
+
# Add funds to create account or top up
|
|
748
|
+
receipt = broker.ledger.add_ledger("0.1")
|
|
749
|
+
|
|
750
|
+
# Deposit more funds
|
|
751
|
+
receipt = broker.ledger.deposit_fund("0.5")
|
|
752
|
+
|
|
753
|
+
# Transfer to provider sub-account
|
|
754
|
+
from zerog_py_sdk.utils import og_to_wei
|
|
755
|
+
broker.ledger.transfer_fund(provider_address, "inference", og_to_wei("0.5"))
|
|
756
|
+
|
|
757
|
+
# Check balance
|
|
758
|
+
account = broker.ledger.get_ledger()
|
|
759
|
+
print(f"Balance: {account.balance} OG")
|
|
760
|
+
print(f"Total: {account.total_balance} OG")
|
|
761
|
+
|
|
762
|
+
# Request refund from all providers
|
|
763
|
+
receipt = broker.ledger.retrieve_fund("inference")
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
### Service Discovery
|
|
767
|
+
|
|
768
|
+
```python
|
|
769
|
+
# List all services
|
|
770
|
+
services = broker.inference.list_service()
|
|
771
|
+
|
|
772
|
+
for service in services:
|
|
773
|
+
print(f"Provider: {service.provider}")
|
|
774
|
+
print(f"Model: {service.model}")
|
|
775
|
+
print(f"URL: {service.url}")
|
|
776
|
+
print(f"Input Price: {service.input_price} wei/token")
|
|
777
|
+
print(f"Output Price: {service.output_price} wei/token")
|
|
778
|
+
print(f"Verifiable: {service.is_verifiable()}")
|
|
779
|
+
|
|
780
|
+
# Get specific service
|
|
781
|
+
service = broker.inference.get_service(provider_address)
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
### Making Requests
|
|
785
|
+
|
|
786
|
+
```python
|
|
787
|
+
import requests
|
|
788
|
+
import json
|
|
789
|
+
|
|
790
|
+
# 1. Acknowledge provider (once per provider)
|
|
791
|
+
broker.inference.acknowledge_provider_signer(provider_address)
|
|
792
|
+
|
|
793
|
+
# 2. Get service info
|
|
794
|
+
metadata = broker.inference.get_service_metadata(provider_address)
|
|
795
|
+
endpoint = metadata['endpoint'] # Already includes /v1/proxy
|
|
796
|
+
model = metadata['model']
|
|
797
|
+
|
|
798
|
+
# 3. Get auth headers (NEW: no content parameter needed!)
|
|
799
|
+
headers = broker.inference.get_request_headers(provider_address)
|
|
800
|
+
|
|
801
|
+
# 4. Make request
|
|
802
|
+
messages = [{"role": "user", "content": "What is the capital of France?"}]
|
|
803
|
+
response = requests.post(
|
|
804
|
+
f"{endpoint}/chat/completions",
|
|
805
|
+
headers={"Content-Type": "application/json", **headers},
|
|
806
|
+
json={"messages": messages, "model": model}
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
# 5. Parse response
|
|
810
|
+
if response.status_code == 200:
|
|
811
|
+
answer = response.json()['choices'][0]['message']['content']
|
|
812
|
+
print(f"Answer: {answer}")
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### Creating Persistent API Keys
|
|
816
|
+
|
|
817
|
+
For server applications that need long-lived credentials:
|
|
818
|
+
|
|
819
|
+
```python
|
|
820
|
+
from zerog_py_sdk import SessionMode
|
|
821
|
+
|
|
822
|
+
# Create an API key that never expires
|
|
823
|
+
api_key_info = broker.inference.session_manager.create_api_key(
|
|
824
|
+
provider_address,
|
|
825
|
+
expires_in=0 # 0 = never expires
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
print(f"API Key: {api_key_info.raw_token}")
|
|
829
|
+
print(f"Token ID: {api_key_info.token_id}")
|
|
830
|
+
|
|
831
|
+
# Use the API key in requests
|
|
832
|
+
headers = {"Authorization": f"Bearer {api_key_info.raw_token}"}
|
|
833
|
+
response = requests.post(
|
|
834
|
+
f"{endpoint}/chat/completions",
|
|
835
|
+
headers={"Content-Type": "application/json", **headers},
|
|
836
|
+
json={"messages": messages, "model": model}
|
|
837
|
+
)
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
### Using with OpenAI SDK
|
|
841
|
+
|
|
842
|
+
```python
|
|
843
|
+
from openai import OpenAI
|
|
844
|
+
|
|
845
|
+
# Get metadata
|
|
846
|
+
metadata = broker.inference.get_service_metadata(provider_address)
|
|
847
|
+
|
|
848
|
+
# Get session token headers (NEW: no content needed!)
|
|
849
|
+
headers = broker.inference.get_request_headers(provider_address)
|
|
850
|
+
|
|
851
|
+
# Create client with Authorization header
|
|
852
|
+
client = OpenAI(
|
|
853
|
+
base_url=metadata['endpoint'],
|
|
854
|
+
api_key="not-used", # Auth via headers
|
|
855
|
+
default_headers=headers
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
# Make request
|
|
859
|
+
completion = client.chat.completions.create(
|
|
860
|
+
model=metadata['model'],
|
|
861
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
print(completion.choices[0].message.content)
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
---
|
|
868
|
+
|
|
869
|
+
## Available Providers (Testnet)
|
|
870
|
+
|
|
871
|
+
Query live providers dynamically:
|
|
872
|
+
|
|
873
|
+
```python
|
|
874
|
+
services = broker.inference.list_service()
|
|
875
|
+
for s in services:
|
|
876
|
+
print(f"{s.model} - {s.provider}")
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
**Example providers (as of Feb 2026):**
|
|
880
|
+
- `qwen/qwen-2.5-7b-instruct` - Qwen 2.5 7B chat model
|
|
881
|
+
- `openai/gpt-oss-20b` - GPT-compatible 20B model
|
|
882
|
+
- `google/gemma-3-27b-it` - Gemma 3 27B instruction-tuned
|
|
883
|
+
- `qwen/qwen-image-edit-2511` - Image editing model
|
|
884
|
+
|
|
885
|
+
All providers use **TeeML** (TEE-verified compute) for security.
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
## Error Handling
|
|
890
|
+
|
|
891
|
+
```python
|
|
892
|
+
from zerog_py_sdk import (
|
|
893
|
+
ZGServingBrokerError,
|
|
894
|
+
InsufficientBalanceError,
|
|
895
|
+
ProviderNotAcknowledgedError,
|
|
896
|
+
ContractError,
|
|
897
|
+
NetworkError
|
|
898
|
+
)
|
|
899
|
+
|
|
900
|
+
try:
|
|
901
|
+
broker.ledger.add_ledger("0.1")
|
|
902
|
+
except InsufficientBalanceError as e:
|
|
903
|
+
print(f"Not enough OG tokens in wallet: {e}")
|
|
904
|
+
except ContractError as e:
|
|
905
|
+
print(f"Smart contract error: {e}")
|
|
906
|
+
except NetworkError as e:
|
|
907
|
+
print(f"RPC connection failed: {e}")
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
---
|
|
911
|
+
|
|
912
|
+
## Troubleshooting
|
|
913
|
+
|
|
914
|
+
### "Transaction failed" when acknowledging provider
|
|
915
|
+
**Cause:** Account doesn't exist yet.
|
|
916
|
+
**Fix:** The SDK now auto-creates accounts. Update to latest version.
|
|
917
|
+
|
|
918
|
+
### "403 Forbidden" from provider
|
|
919
|
+
**Cause:** Missing `/v1/proxy` in endpoint URL.
|
|
920
|
+
**Fix:** Use `get_service_metadata()` - it adds the proxy path automatically.
|
|
921
|
+
|
|
922
|
+
### "401 Unauthorized" from provider
|
|
923
|
+
**Cause:** Invalid or expired session token.
|
|
924
|
+
**Fix:** Session tokens are auto-refreshed. If using API keys, check expiration.
|
|
925
|
+
|
|
926
|
+
### "Insufficient balance"
|
|
927
|
+
**Cause:** No funds in account or not transferred to provider.
|
|
928
|
+
**Fix:**
|
|
929
|
+
```python
|
|
930
|
+
# Add to main ledger
|
|
931
|
+
broker.ledger.deposit_fund("2")
|
|
932
|
+
|
|
933
|
+
# Transfer to provider
|
|
934
|
+
from zerog_py_sdk.utils import og_to_wei
|
|
935
|
+
broker.ledger.transfer_fund(provider, "inference", og_to_wei("0.5"))
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
### "Provider not found" or empty service list
|
|
939
|
+
**Cause:** Wrong network or no providers registered.
|
|
940
|
+
**Fix:** Ensure you're connected to the correct network (testnet vs mainnet).
|
|
941
|
+
|
|
942
|
+
```python
|
|
943
|
+
# Check which network you're on
|
|
944
|
+
chain_id = broker.web3.eth.chain_id
|
|
945
|
+
print(f"Chain ID: {chain_id}") # 16602 = testnet, 16661 = mainnet
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## Architecture Deep Dive
|
|
951
|
+
|
|
952
|
+
### Pure Python Implementation
|
|
953
|
+
|
|
954
|
+
The SDK is now 100% Python with native cryptographic implementations:
|
|
955
|
+
|
|
956
|
+
**Python Benefits:**
|
|
957
|
+
- ✅ No Node.js/npm dependency
|
|
958
|
+
- ✅ Rich ML/AI ecosystem
|
|
959
|
+
- ✅ Web3.py for Ethereum
|
|
960
|
+
- ✅ Easy HTTP requests
|
|
961
|
+
- ✅ Familiar to AI engineers
|
|
962
|
+
|
|
963
|
+
**Native Crypto:**
|
|
964
|
+
- ✅ Baby JubJub elliptic curve
|
|
965
|
+
- ✅ EdDSA signatures
|
|
966
|
+
- ✅ Pedersen hash
|
|
967
|
+
- ✅ Compatible with TypeScript SDK
|
|
968
|
+
|
|
969
|
+
**Architecture:**
|
|
970
|
+
```
|
|
971
|
+
Python SDK
|
|
972
|
+
│
|
|
973
|
+
├── Web3.py ────────> Blockchain (RPC)
|
|
974
|
+
│ │
|
|
975
|
+
│ ├── LedgerManager contract
|
|
976
|
+
│ └── InferenceServing contract
|
|
977
|
+
│
|
|
978
|
+
├── Requests ───────> AI Provider (HTTP)
|
|
979
|
+
│ │
|
|
980
|
+
│ └── OpenAI-compatible API
|
|
981
|
+
│
|
|
982
|
+
└── crypto/ ────────> Native Python
|
|
983
|
+
│
|
|
984
|
+
├── EdDSA signatures
|
|
985
|
+
└── Pedersen hash
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
### Smart Contract Interaction
|
|
989
|
+
|
|
990
|
+
The SDK interacts with two main contracts:
|
|
991
|
+
|
|
992
|
+
**1. LedgerManager** (`0x5e583B...`)
|
|
993
|
+
- Manages user accounts and balances
|
|
994
|
+
- Handles deposits, withdrawals, transfers
|
|
995
|
+
- Tracks provider allocations
|
|
996
|
+
|
|
997
|
+
**2. InferenceServing** (`0x8e893C...`)
|
|
998
|
+
- Registers AI providers
|
|
999
|
+
- Stores service metadata (models, pricing, URLs)
|
|
1000
|
+
- Verifies TEE signers
|
|
1001
|
+
- Settles usage-based billing
|
|
1002
|
+
|
|
1003
|
+
---
|
|
1004
|
+
|
|
1005
|
+
## Get Testnet Tokens
|
|
1006
|
+
|
|
1007
|
+
Need 0G tokens for testing?
|
|
1008
|
+
|
|
1009
|
+
1. Get wallet address: `broker.get_address()`
|
|
1010
|
+
2. Visit faucet: https://faucet.0g.ai
|
|
1011
|
+
3. Paste your address and request tokens
|
|
1012
|
+
|
|
1013
|
+
---
|
|
1014
|
+
|
|
1015
|
+
## Contributing
|
|
1016
|
+
|
|
1017
|
+
Contributions welcome! Please:
|
|
1018
|
+
|
|
1019
|
+
1. Fork the repository
|
|
1020
|
+
2. Create a feature branch
|
|
1021
|
+
3. Make your changes
|
|
1022
|
+
4. Add tests
|
|
1023
|
+
5. Submit a pull request
|
|
1024
|
+
|
|
1025
|
+
### Development Setup
|
|
1026
|
+
|
|
1027
|
+
Follow the installation steps above, then:
|
|
1028
|
+
|
|
1029
|
+
```bash
|
|
1030
|
+
# Make your changes to the SDK files
|
|
1031
|
+
# The SDK is in zerog_py_sdk/ directory
|
|
1032
|
+
|
|
1033
|
+
# Test your changes
|
|
1034
|
+
python3 test.py
|
|
1035
|
+
|
|
1036
|
+
# Or create your own test script
|
|
1037
|
+
python3 your_script.py
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
### Project Structure
|
|
1041
|
+
|
|
1042
|
+
```
|
|
1043
|
+
0g_py_inference/
|
|
1044
|
+
├── zerog_py_sdk/ # Main SDK package
|
|
1045
|
+
│ ├── __init__.py # Public API exports
|
|
1046
|
+
│ ├── broker.py # Broker implementation
|
|
1047
|
+
│ ├── ledger.py # Ledger manager
|
|
1048
|
+
│ ├── inference.py # Inference manager
|
|
1049
|
+
│ ├── session.py # Session token management (NEW)
|
|
1050
|
+
│ ├── read_only.py # Read-only broker (NEW)
|
|
1051
|
+
│ ├── constants.py # Network constants (NEW)
|
|
1052
|
+
│ ├── extractors.py # Service type extractors (NEW)
|
|
1053
|
+
│ ├── cache.py # Caching system (NEW)
|
|
1054
|
+
│ ├── verifier.py # Response verification (NEW)
|
|
1055
|
+
│ ├── auth.py # Authentication utilities
|
|
1056
|
+
│ ├── models.py # Data models
|
|
1057
|
+
│ ├── exceptions.py # Custom exceptions
|
|
1058
|
+
│ ├── utils.py # Helper functions
|
|
1059
|
+
│ ├── crypto/ # Native Python crypto (NEW)
|
|
1060
|
+
│ │ ├── eddsa.py # EdDSA signatures
|
|
1061
|
+
│ │ ├── pedersen.py # Pedersen hash
|
|
1062
|
+
│ │ └── baby_jubjub.py # Baby JubJub curve
|
|
1063
|
+
│ └── contracts/ # Contract ABIs
|
|
1064
|
+
│ └── abis.py # Updated ABI definitions
|
|
1065
|
+
├── test.py # Working example script
|
|
1066
|
+
├── requirements.txt # Python dependencies
|
|
1067
|
+
├── .env # Environment variables (create this)
|
|
1068
|
+
└── README.md # This file
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
---
|
|
1072
|
+
|
|
1073
|
+
## License
|
|
1074
|
+
|
|
1075
|
+
MIT License - see LICENSE file for details.
|
|
1076
|
+
|
|
1077
|
+
---
|
|
1078
|
+
|
|
1079
|
+
## Links
|
|
1080
|
+
|
|
1081
|
+
- [0G Documentation](https://docs.0g.ai/)
|
|
1082
|
+
- [TypeScript SDK](https://github.com/0glabs/0g-serving-broker)
|
|
1083
|
+
- [Compute Network Docs](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/sdk)
|
|
1084
|
+
- [Author Twitter/X](https://x.com/damiclone)
|
|
1085
|
+
|
|
1086
|
+
---
|
|
1087
|
+
|
|
1088
|
+
## Support
|
|
1089
|
+
|
|
1090
|
+
For issues and questions:
|
|
1091
|
+
- **GitHub Issues**: [Report a bug](https://github.com/0glabs/0g-compute-sdk-python/issues)
|
|
1092
|
+
- **Discord**: [0G Labs Community](https://discord.gg/0glabs)
|
|
1093
|
+
- **Documentation**: [docs.0g.ai](https://docs.0g.ai/)
|
|
1094
|
+
|
|
1095
|
+
---
|
|
1096
|
+
|
|
1097
|
+
## Changelog
|
|
1098
|
+
|
|
1099
|
+
### v0.2.0 (Latest - Feb 2026)
|
|
1100
|
+
- ✅ **Session Token Auth**: New simplified authorization system (no content parameter needed)
|
|
1101
|
+
- ✅ **No Node.js Dependency**: Native Python crypto implementation
|
|
1102
|
+
- ✅ **Read-Only Broker**: Browse services without wallet connection
|
|
1103
|
+
- ✅ **Multi-Network Support**: Mainnet/testnet with auto-detection
|
|
1104
|
+
- ✅ **API Key Management**: Create persistent, revocable API keys
|
|
1105
|
+
- ✅ **Response Verification**: Verify TEE-signed responses
|
|
1106
|
+
- ✅ **Caching System**: Built-in caching for performance
|
|
1107
|
+
- ✅ **Service Extractors**: Support for chatbot, image, speech services
|
|
1108
|
+
- ✅ **Updated ABIs**: Compatible with latest 0G contracts
|
|
1109
|
+
|
|
1110
|
+
### v0.1.0
|
|
1111
|
+
- ✅ Fixed endpoint URL - now correctly appends `/v1/proxy`
|
|
1112
|
+
- ✅ Auto-creates accounts when acknowledging providers
|
|
1113
|
+
- ✅ Improved error handling
|
|
1114
|
+
- ✅ Added complete working example
|
|
1115
|
+
- ✅ Full documentation with architecture details
|