z0gcode 0.2.0

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.
@@ -0,0 +1,229 @@
1
+ # Chain Patterns
2
+
3
+ EVM patterns, deployment configurations, and best practices for 0G Chain.
4
+
5
+ ## Overview
6
+
7
+ 0G Chain is an EVM-compatible Layer 1 blockchain. It supports standard Solidity smart contracts with
8
+ a critical requirement: **all contracts must be compiled with `evmVersion: "cancun"`**.
9
+
10
+ ## Hardhat Configuration
11
+
12
+ ```typescript
13
+ // hardhat.config.ts
14
+ import { HardhatUserConfig } from 'hardhat/config';
15
+ import '@nomicfoundation/hardhat-toolbox';
16
+ import 'dotenv/config';
17
+
18
+ const config: HardhatUserConfig = {
19
+ solidity: {
20
+ version: '0.8.24',
21
+ settings: {
22
+ optimizer: { enabled: true, runs: 200 },
23
+ evmVersion: 'cancun', // REQUIRED for 0G Chain
24
+ },
25
+ },
26
+ networks: {
27
+ '0g-testnet': {
28
+ url: 'https://evmrpc-testnet.0g.ai',
29
+ chainId: 16602,
30
+ accounts: [process.env.PRIVATE_KEY!],
31
+ },
32
+ '0g-mainnet': {
33
+ url: 'https://evmrpc.0g.ai',
34
+ chainId: 16661,
35
+ accounts: [process.env.PRIVATE_KEY!],
36
+ },
37
+ },
38
+ };
39
+
40
+ export default config;
41
+ ```
42
+
43
+ ## Foundry Configuration
44
+
45
+ ```toml
46
+ # foundry.toml
47
+ [profile.default]
48
+ src = "src"
49
+ out = "out"
50
+ libs = ["lib"]
51
+ evm_version = "cancun" # REQUIRED for 0G Chain
52
+ solc_version = "0.8.24"
53
+ optimizer = true
54
+ optimizer_runs = 200
55
+
56
+ [rpc_endpoints]
57
+ 0g_testnet = "https://evmrpc-testnet.0g.ai"
58
+ 0g_mainnet = "https://evmrpc.0g.ai"
59
+ ```
60
+
61
+ ## Contract Deployment
62
+
63
+ ### With Hardhat
64
+
65
+ ```typescript
66
+ // scripts/deploy.ts
67
+ import { ethers } from 'hardhat';
68
+
69
+ async function main() {
70
+ const [deployer] = await ethers.getSigners();
71
+ console.log('Deploying with:', deployer.address);
72
+
73
+ const Contract = await ethers.getContractFactory('MyContract');
74
+ const contract = await Contract.deploy(/* constructor args */);
75
+ await contract.waitForDeployment();
76
+
77
+ const address = await contract.getAddress();
78
+ console.log('Deployed to:', address);
79
+ }
80
+
81
+ main().catch(console.error);
82
+ ```
83
+
84
+ ```bash
85
+ npx hardhat run scripts/deploy.ts --network 0g-testnet
86
+ ```
87
+
88
+ ### With Foundry
89
+
90
+ ```bash
91
+ forge create src/MyContract.sol:MyContract \
92
+ --rpc-url https://evmrpc-testnet.0g.ai \
93
+ --private-key $PRIVATE_KEY \
94
+ --constructor-args "arg1" "arg2"
95
+ ```
96
+
97
+ ### With ethers v6 (Direct)
98
+
99
+ ```typescript
100
+ import { ethers, ContractFactory } from 'ethers';
101
+ import 'dotenv/config';
102
+
103
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
104
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
105
+
106
+ // ABI and bytecode from compilation output
107
+ const factory = new ContractFactory(abi, bytecode, wallet);
108
+ const contract = await factory.deploy(/* constructor args */);
109
+ await contract.waitForDeployment();
110
+
111
+ console.log('Deployed to:', await contract.getAddress());
112
+ ```
113
+
114
+ ## Contract Interaction
115
+
116
+ ### Read (View Functions)
117
+
118
+ ```typescript
119
+ import { ethers } from 'ethers';
120
+
121
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
122
+ const contract = new ethers.Contract(contractAddress, abi, provider);
123
+
124
+ // Read-only calls (no gas)
125
+ const value = await contract.getValue();
126
+ const balance = await contract.balanceOf(address);
127
+ ```
128
+
129
+ ### Write (State-Changing Functions)
130
+
131
+ ```typescript
132
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
133
+ const contract = new ethers.Contract(contractAddress, abi, wallet);
134
+
135
+ // State-changing calls (costs gas)
136
+ const tx = await contract.setValue(42);
137
+ const receipt = await tx.wait();
138
+ console.log('Tx hash:', receipt.hash);
139
+ ```
140
+
141
+ ### Events
142
+
143
+ ```typescript
144
+ // Listen for events
145
+ contract.on('Transfer', (from, to, amount) => {
146
+ console.log(`Transfer: ${from} → ${to}: ${amount}`);
147
+ });
148
+
149
+ // Query past events
150
+ const filter = contract.filters.Transfer(null, myAddress);
151
+ const events = await contract.queryFilter(filter, fromBlock, toBlock);
152
+ ```
153
+
154
+ ## ethers v6 Migration Notes
155
+
156
+ 0G Chain examples use ethers v6 exclusively. Key differences from v5:
157
+
158
+ | v5 (DO NOT USE) | v6 (CORRECT) |
159
+ | ---------------------------------- | ------------------------------ |
160
+ | `ethers.providers.JsonRpcProvider` | `ethers.JsonRpcProvider` |
161
+ | `ethers.utils.parseEther` | `ethers.parseEther` |
162
+ | `ethers.utils.formatEther` | `ethers.formatEther` |
163
+ | `contract.deployed()` | `contract.waitForDeployment()` |
164
+ | `contract.address` | `await contract.getAddress()` |
165
+ | `BigNumber.from()` | Native `BigInt` |
166
+ | `ethers.utils.keccak256` | `ethers.keccak256` |
167
+
168
+ ## Gas Estimation
169
+
170
+ ```typescript
171
+ const gasEstimate = await contract.setValue.estimateGas(42);
172
+ console.log('Estimated gas:', gasEstimate.toString());
173
+
174
+ // With manual gas limit
175
+ const tx = await contract.setValue(42, {
176
+ gasLimit: (gasEstimate * 120n) / 100n, // 20% buffer
177
+ });
178
+ ```
179
+
180
+ ## Verification
181
+
182
+ ### Hardhat Verify
183
+
184
+ ```bash
185
+ npx hardhat verify --network 0g-testnet <CONTRACT_ADDRESS> "arg1" "arg2"
186
+ ```
187
+
188
+ ### Foundry Verify
189
+
190
+ ```bash
191
+ forge verify-contract <CONTRACT_ADDRESS> src/MyContract.sol:MyContract \
192
+ --chain-id 16602 \
193
+ --verifier-url https://chainscan-galileo.0g.ai/api
194
+ ```
195
+
196
+ ## Critical Rules
197
+
198
+ ### ALWAYS
199
+
200
+ - Use `evmVersion: "cancun"` in compiler settings
201
+ - Use ethers v6 syntax (NOT v5)
202
+ - Load private keys from environment variables
203
+ - Wait for transaction confirmation (`tx.wait()`)
204
+ - Test on testnet before mainnet deployment
205
+
206
+ ### NEVER
207
+
208
+ - Use `evmVersion` other than `"cancun"` for 0G Chain
209
+ - Use ethers v5 patterns (`ethers.providers`, `ethers.utils`, etc.)
210
+ - Hardcode private keys in source files
211
+ - Deploy to mainnet without testnet validation
212
+
213
+ ## Common Errors
214
+
215
+ | Error | Cause | Fix |
216
+ | --------------------- | -------------------- | ------------------------------- |
217
+ | `invalid opcode` | Wrong evmVersion | Set `evmVersion: "cancun"` |
218
+ | `execution reverted` | Contract logic error | Check require/revert conditions |
219
+ | `insufficient funds` | Wallet empty | Fund from faucet (testnet) |
220
+ | `nonce too low` | Pending tx | Wait or manually set nonce |
221
+ | `cannot estimate gas` | Function will revert | Check function parameters |
222
+
223
+ ## References
224
+
225
+ - [0G Chain Docs](https://docs.0g.ai/build-with-0g/0g-chain)
226
+ - [Hardhat Documentation](https://hardhat.org/docs)
227
+ - [Foundry Documentation](https://book.getfoundry.sh)
228
+ - [ethers v6 Migration](https://docs.ethers.org/v6/migrating/)
229
+ - See also: [NETWORK_CONFIG.md](./NETWORK_CONFIG.md), [SECURITY.md](./SECURITY.md)
@@ -0,0 +1,296 @@
1
+ # Compute Patterns
2
+
3
+ Architecture, broker lifecycle, processResponse() deep-dive, and best practices for 0G decentralized
4
+ compute.
5
+
6
+ ## Architecture Overview
7
+
8
+ ```
9
+ ┌────────────────────────────────────┐
10
+ │ Your Application │
11
+ ├────────────────────────────────────┤
12
+ │ 0G Serving Broker SDK │
13
+ │ (@0glabs/0g-serving-broker) │
14
+ ├────────────────────────────────────┤
15
+ │ Provider Network │
16
+ │ (TEE-verified GPU nodes) │
17
+ ├────────────────────────────────────┤
18
+ │ 0G Chain │
19
+ │ (Settlement & verification) │
20
+ └────────────────────────────────────┘
21
+ ```
22
+
23
+ ## Service Types
24
+
25
+ | Type | Endpoint Path | Models | Use Case |
26
+ | ---------------- | ----------------------- | ----------------------------------- | ------------------- |
27
+ | `chatbot` | `/chat/completions` | DeepSeek V3.1, Qwen, Gemma, GPT-OSS | Conversational AI |
28
+ | `text-to-image` | `/images/generations` | Flux Turbo | Image generation |
29
+ | `speech-to-text` | `/audio/transcriptions` | Whisper Large V3 | Audio transcription |
30
+
31
+ ## Broker Lifecycle
32
+
33
+ ### 1. Initialize Broker
34
+
35
+ ```typescript
36
+ import { ethers } from 'ethers';
37
+ import { createZGComputeNetworkBroker } from '@0glabs/0g-serving-broker';
38
+
39
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
40
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
41
+ const broker = await createZGComputeNetworkBroker(wallet);
42
+ ```
43
+
44
+ ### 2. Discover Providers
45
+
46
+ ```typescript
47
+ const services = await broker.inference.listService();
48
+
49
+ // Services are returned as tuple arrays:
50
+ // [0] = providerAddress, [1] = serviceType, [2] = url,
51
+ // [6] = model, [10] = teeVerified
52
+ const chatbotServices = services.filter((s: any) => s[1] === 'chatbot');
53
+ const imageServices = services.filter((s: any) => s[1] === 'text-to-image');
54
+ const speechServices = services.filter((s: any) => s[1] === 'speech-to-text');
55
+
56
+ // Access provider info: s[0] = address, s[6] = model, s[10] = TEE verified
57
+ ```
58
+
59
+ ### 3. Fund Account
60
+
61
+ ```typescript
62
+ // Deposit to main account
63
+ await broker.ledger.depositFund(10);
64
+
65
+ // Transfer to provider sub-account
66
+ await broker.ledger.transferFund(providerAddress, 'inference', ethers.parseEther('5'));
67
+
68
+ // Acknowledge provider (one-time per provider)
69
+ await broker.inference.acknowledgeProviderSigner(providerAddress);
70
+ ```
71
+
72
+ ### 4. Get Service Metadata
73
+
74
+ ```typescript
75
+ const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
76
+ ```
77
+
78
+ ### 5. Generate Auth Headers
79
+
80
+ ```typescript
81
+ // For chatbot (no body needed)
82
+ const headers = await broker.inference.getRequestHeaders(providerAddress);
83
+
84
+ // For text-to-image (body MUST be included for signing)
85
+ const headers = await broker.inference.getRequestHeaders(
86
+ providerAddress,
87
+ JSON.stringify(requestBody),
88
+ );
89
+ ```
90
+
91
+ ### 6. Make Request & Process Response
92
+
93
+ See the processResponse() section below — this is the most critical step.
94
+
95
+ ## processResponse() Deep-Dive
96
+
97
+ **This is the most important function in the 0G Compute SDK.** It MUST be called after every
98
+ inference request for fee settlement and response verification.
99
+
100
+ ### Signature
101
+
102
+ ```typescript
103
+ await broker.inference.processResponse(
104
+ providerAddress, // string — provider's Ethereum address
105
+ chatID, // string | undefined — response identifier
106
+ usageData, // string | undefined — JSON-stringified usage stats
107
+ );
108
+ ```
109
+
110
+ ### Parameter Order is CRITICAL
111
+
112
+ ```
113
+ processResponse(providerAddress, chatID, usageData)
114
+ ↑ FIRST ↑ SECOND ↑ THIRD
115
+ ```
116
+
117
+ Getting the order wrong will cause silent fee miscalculation.
118
+
119
+ ### ChatID Extraction Rules
120
+
121
+ | Service Type | Primary Source | Fallback |
122
+ | ----------------------- | ------------------------------------ | ------------------------------- |
123
+ | Chatbot (non-streaming) | `response.headers.get("ZG-Res-Key")` | `data.id` from response body |
124
+ | Chatbot (streaming) | `response.headers.get("ZG-Res-Key")` | `message.id` from stream chunks |
125
+ | Text-to-Image | `response.headers.get("ZG-Res-Key")` | None |
126
+ | Speech-to-Text | `response.headers.get("ZG-Res-Key")` | None |
127
+
128
+ **ALWAYS check headers first, body as fallback (chatbot only):**
129
+
130
+ ```typescript
131
+ let chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
132
+ if (!chatID) {
133
+ chatID = data.id; // Fallback for chatbot only
134
+ }
135
+ ```
136
+
137
+ ### Usage Data by Service Type
138
+
139
+ | Service Type | Usage Data Required | Format |
140
+ | -------------- | ------------------- | ---------------------------- |
141
+ | Chatbot | Yes | `JSON.stringify(data.usage)` |
142
+ | Text-to-Image | No | Omit or pass `undefined` |
143
+ | Speech-to-Text | Yes (if available) | `JSON.stringify(data.usage)` |
144
+
145
+ ### Complete Examples
146
+
147
+ #### Chatbot processResponse
148
+
149
+ ```typescript
150
+ const data = await response.json();
151
+ let chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
152
+ if (!chatID) chatID = data.id;
153
+
154
+ await broker.inference.processResponse(providerAddress, chatID, JSON.stringify(data.usage));
155
+ ```
156
+
157
+ #### Text-to-Image processResponse
158
+
159
+ ```typescript
160
+ const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
161
+
162
+ if (chatID) {
163
+ await broker.inference.processResponse(providerAddress, chatID);
164
+ }
165
+ ```
166
+
167
+ #### Speech-to-Text processResponse
168
+
169
+ ```typescript
170
+ const data = await response.json();
171
+ const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
172
+
173
+ await broker.inference.processResponse(
174
+ providerAddress,
175
+ chatID,
176
+ data.usage ? JSON.stringify(data.usage) : undefined,
177
+ );
178
+ ```
179
+
180
+ ## Streaming Pattern
181
+
182
+ ```typescript
183
+ const response = await fetch(`${endpoint}/chat/completions`, {
184
+ method: 'POST',
185
+ headers: { 'Content-Type': 'application/json', ...headers },
186
+ body: JSON.stringify({ messages, model, stream: true }),
187
+ });
188
+
189
+ let chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
190
+ let usage = null;
191
+ let streamChatID = null;
192
+
193
+ const decoder = new TextDecoder();
194
+ const reader = response.body!.getReader();
195
+ let rawBody = '';
196
+
197
+ while (true) {
198
+ const { done, value } = await reader.read();
199
+ if (done) break;
200
+ const chunk = decoder.decode(value, { stream: true });
201
+ rawBody += chunk;
202
+ process.stdout.write(chunk); // Real-time output
203
+ }
204
+
205
+ // Parse stream for chatID fallback and usage
206
+ for (const line of rawBody.split('\n')) {
207
+ const trimmed = line.trim();
208
+ if (!trimmed || trimmed === 'data: [DONE]') continue;
209
+ try {
210
+ const jsonStr = trimmed.startsWith('data:') ? trimmed.slice(5).trim() : trimmed;
211
+ const message = JSON.parse(jsonStr);
212
+ if (!streamChatID && message.id) streamChatID = message.id;
213
+ if (message.usage) usage = message.usage;
214
+ } catch {}
215
+ }
216
+
217
+ const finalChatID = chatID || streamChatID;
218
+ await broker.inference.processResponse(providerAddress, finalChatID, JSON.stringify(usage || {}));
219
+ ```
220
+
221
+ ## Account Structure
222
+
223
+ ```
224
+ Your Wallet
225
+ ↓ deposit
226
+ Main Account
227
+ ↓ transfer-fund
228
+ Provider Sub-Accounts (one per provider)
229
+ ↓ service usage (auto-deducted)
230
+ ↓ retrieve-fund (24h lock)
231
+ Main Account
232
+ ↓ refund
233
+ Your Wallet
234
+ ```
235
+
236
+ ## TEE Verification
237
+
238
+ Trusted Execution Environment verification ensures provider integrity:
239
+
240
+ ```typescript
241
+ const services = await broker.inference.listService();
242
+ // Tuple: [0]=providerAddress, [1]=serviceType, [10]=teeVerified
243
+ for (const service of services) {
244
+ if (service[0] === targetProvider) {
245
+ console.log('TEE verified:', service[10]);
246
+ }
247
+ }
248
+ ```
249
+
250
+ ## CLI Commands Reference
251
+
252
+ | Action | Command |
253
+ | -------------------- | ----------------------------------------------------------------- |
254
+ | Setup network | `0g-compute-cli setup-network` |
255
+ | Login | `0g-compute-cli login` |
256
+ | Deposit | `0g-compute-cli deposit --amount 10` |
257
+ | Check balance | `0g-compute-cli get-account` |
258
+ | Transfer to provider | `0g-compute-cli transfer-fund --provider <ADDR> --amount 5` |
259
+ | Acknowledge provider | `0g-compute-cli inference acknowledge-provider --provider <ADDR>` |
260
+ | List providers | `0g-compute-cli inference list-providers` |
261
+ | Start local proxy | `0g-compute-cli inference serve --provider <ADDR>` |
262
+ | Get API secret | `0g-compute-cli inference get-secret --provider <ADDR>` |
263
+
264
+ ## Critical Rules
265
+
266
+ ### ALWAYS
267
+
268
+ - Call `processResponse()` after EVERY inference request
269
+ - Use correct parameter order: `(providerAddress, chatID, usageData)`
270
+ - Extract ChatID from `ZG-Res-Key` header first, body as fallback
271
+ - Acknowledge provider before first use
272
+ - Check balance before making requests
273
+
274
+ ### NEVER
275
+
276
+ - Skip `processResponse()` — causes fee settlement failure
277
+ - Reverse the parameter order of `processResponse()`
278
+ - Hardcode private keys
279
+ - Use ethers v5 syntax (use v6)
280
+ - Skip provider acknowledgment
281
+
282
+ ## Common Errors
283
+
284
+ | Error | Cause | Fix |
285
+ | --------------------------- | -------------------------------- | ---------------------------------------------- |
286
+ | `Insufficient balance` | Sub-account empty | Transfer funds: `broker.ledger.transferFund()` |
287
+ | `Provider not acknowledged` | First-time use | `broker.inference.acknowledgeProviderSigner()` |
288
+ | `Invalid request headers` | Stale auth | Re-call `getRequestHeaders()` |
289
+ | `Fee verification failed` | Wrong `processResponse()` params | Check param order and chatID source |
290
+ | `Connection refused` | Wrong RPC URL | Verify RPC_URL in .env |
291
+
292
+ ## References
293
+
294
+ - [0G Compute SDK Docs](https://docs.0g.ai/build-with-0g/compute-network/sdk)
295
+ - [0G Serving Broker](https://github.com/0gfoundation/0g-serving-broker)
296
+ - See also: [NETWORK_CONFIG.md](./NETWORK_CONFIG.md), [SECURITY.md](./SECURITY.md)
@@ -0,0 +1,163 @@
1
+ # Network Configuration
2
+
3
+ Single source of truth for all 0G network endpoints, chain IDs, SDK versions, and environment setup.
4
+
5
+ ## Network Environments
6
+
7
+ ### Testnet (Galileo — Recommended for Development)
8
+
9
+ | Parameter | Value |
10
+ | --------------- | --------------------------------------------- |
11
+ | Network Name | 0G-Galileo-Testnet |
12
+ | RPC Endpoint | `https://evmrpc-testnet.0g.ai` |
13
+ | Chain ID | `16602` |
14
+ | Currency Symbol | 0G |
15
+ | Block Explorer | `https://chainscan-galileo.0g.ai` |
16
+ | Storage RPC | `https://storagerpc-testnet.0g.ai` |
17
+ | Storage Indexer | `https://indexer-storage-testnet-turbo.0g.ai` |
18
+
19
+ ### Mainnet (Aristotle)
20
+
21
+ | Parameter | Value |
22
+ | --------------- | ------------------------------------- |
23
+ | Network Name | 0G Mainnet |
24
+ | RPC Endpoint | `https://evmrpc.0g.ai` |
25
+ | Chain ID | `16661` |
26
+ | Currency Symbol | 0G |
27
+ | Block Explorer | `https://chainscan.0g.ai` |
28
+ | Storage RPC | `https://storagerpc.0g.ai` |
29
+ | Storage Indexer | `https://indexer-storage-turbo.0g.ai` |
30
+
31
+ ## SDK Versions
32
+
33
+ | Package | Version | Purpose |
34
+ | --------------------------- | --------- | ------------------------------------------- |
35
+ | `@0glabs/0g-ts-sdk` | `^0.3.3` | Storage operations (upload, download) |
36
+ | `@0glabs/0g-serving-broker` | `^0.6.5` | Compute operations (inference, fine-tuning) |
37
+ | `ethers` | `^6.13.0` | Chain interaction (MUST be v6, NOT v5) |
38
+ | `dotenv` | `^16.4.0` | Environment variable management |
39
+
40
+ ## Environment Variables Template
41
+
42
+ ```bash
43
+ # .env — NEVER commit this file
44
+
45
+ # Network Configuration
46
+ RPC_URL=https://evmrpc-testnet.0g.ai
47
+ CHAIN_ID=16602
48
+
49
+ # Wallet (NEVER hardcode in source files)
50
+ PRIVATE_KEY=your_private_key_here
51
+
52
+ # Storage Endpoints
53
+ STORAGE_INDEXER=https://indexer-storage-testnet-turbo.0g.ai
54
+
55
+ # Compute
56
+ PROVIDER_ADDRESS=your_provider_address
57
+
58
+ # Optional
59
+ OUTPUT_DIR=./output
60
+ ```
61
+
62
+ ## SDK Initialization Patterns
63
+
64
+ ### ethers v6 Provider (Chain)
65
+
66
+ ```typescript
67
+ import { ethers } from 'ethers';
68
+ import 'dotenv/config';
69
+
70
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
71
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
72
+ ```
73
+
74
+ ### Storage Client
75
+
76
+ ```typescript
77
+ import { ZgFile, Indexer } from '@0glabs/0g-ts-sdk';
78
+ import { ethers } from 'ethers';
79
+
80
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
81
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
82
+ const indexer = new Indexer(process.env.STORAGE_INDEXER!);
83
+ ```
84
+
85
+ ### Compute Broker
86
+
87
+ ```typescript
88
+ import { ethers } from 'ethers';
89
+ import { createZGComputeNetworkBroker } from '@0glabs/0g-serving-broker';
90
+
91
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
92
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
93
+ const broker = await createZGComputeNetworkBroker(wallet);
94
+ ```
95
+
96
+ ### Browser Environment (Compute)
97
+
98
+ ```typescript
99
+ import { BrowserProvider } from 'ethers';
100
+ import { createZGComputeNetworkBroker } from '@0glabs/0g-serving-broker';
101
+
102
+ if (typeof window.ethereum === 'undefined') {
103
+ throw new Error('Please install MetaMask');
104
+ }
105
+
106
+ const provider = new BrowserProvider(window.ethereum);
107
+ const signer = await provider.getSigner();
108
+ const broker = await createZGComputeNetworkBroker(signer);
109
+ ```
110
+
111
+ ## Browser Polyfills
112
+
113
+ When using 0G SDKs in browser environments:
114
+
115
+ ```bash
116
+ pnpm add -D vite-plugin-node-polyfills
117
+ ```
118
+
119
+ ```javascript
120
+ // vite.config.js
121
+ import { nodePolyfills } from 'vite-plugin-node-polyfills';
122
+
123
+ export default {
124
+ plugins: [
125
+ nodePolyfills({
126
+ include: ['crypto', 'stream', 'util', 'buffer', 'process'],
127
+ globals: { Buffer: true, global: true, process: true },
128
+ }),
129
+ ],
130
+ };
131
+ ```
132
+
133
+ ## Network Selection Helper
134
+
135
+ ```typescript
136
+ type Network = 'testnet' | 'mainnet';
137
+
138
+ function getNetworkConfig(network: Network) {
139
+ const configs = {
140
+ testnet: {
141
+ rpcUrl: 'https://evmrpc-testnet.0g.ai',
142
+ chainId: 16602,
143
+ storageRpc: 'https://storagerpc-testnet.0g.ai',
144
+ storageIndexer: 'https://indexer-storage-testnet-turbo.0g.ai',
145
+ explorer: 'https://chainscan-galileo.0g.ai',
146
+ },
147
+ mainnet: {
148
+ rpcUrl: 'https://evmrpc.0g.ai',
149
+ chainId: 16661,
150
+ storageRpc: 'https://storagerpc.0g.ai',
151
+ storageIndexer: 'https://indexer-storage-turbo.0g.ai',
152
+ explorer: 'https://chainscan.0g.ai',
153
+ },
154
+ };
155
+ return configs[network];
156
+ }
157
+ ```
158
+
159
+ ## References
160
+
161
+ - [0G Testnet Info](https://docs.0g.ai/run-a-node/testnet-information)
162
+ - [0G Storage SDK](https://docs.0g.ai/build-with-0g/storage-network/sdk)
163
+ - [0G Compute SDK](https://docs.0g.ai/build-with-0g/compute-network/sdk)