# 0G Documentation > 0G is the trust layer for AI. It combines private compute, encrypted storage, and an AI-native EVM L1 chain in one stack where AI work, from inference to agent actions, is verified and audited. This file contains the full text of every page on https://docs.0g.ai in one document, following the llmstxt.org standard. Each page starts with a heading and a Source line with its markdown URL. For a sectioned index of pages use https://docs.0g.ai/llms.txt; append .md to any docs URL for that single page as markdown. ## AI Coding Context Source: https://docs.0g.ai/ai-context.md This page provides comprehensive context about 0G infrastructure to help AI coding assistants help developers build on 0G. All information is extracted from the official documentation at https://docs.0g.ai. ## Network Configurations ### Testnet (Galileo) **Explorer**: [https://explorer.0g.ai/testnet/home](https://explorer.0g.ai/testnet/home) | Parameter | Value | |-----------|-------| | **Network Name** | 0G Galileo Testnet | | **Chain ID** | 16602 | | **Token Symbol** | 0G | | **RPC Endpoint** | https://evmrpc-testnet.0g.ai (development only — use 3rd party RPCs for production) | | **Block Explorer** | https://chainscan-galileo.0g.ai | | **Storage Explorer** | https://storagescan-galileo.0g.ai | | **Faucet** | https://faucet.0g.ai (0.1 0G/day) | | **Faucet (Google Cloud)** | https://cloud.google.com/application/web3/faucet/0g/galileo | | **Storage Indexer** | https://indexer-storage-testnet-turbo.0g.ai (API base URL; root `/` may return 404) | | **Storage Start Block** | 1 | | **DA Start Block** | 940000 | **Documentation**: [https://docs.0g.ai/developer-hub/testnet/testnet-overview](https://docs.0g.ai/developer-hub/testnet/testnet-overview) **Third-Party RPCs (Recommended for Production)**: - QuickNode: https://www.quicknode.com/chains/0g - ThirdWeb: https://thirdweb.com/16602 - Ankr: https://www.ankr.com/rpc/0g/ - dRPC: https://drpc.org/chainlist/0g-galileo-testnet-rpc - dRPC NodeCloud: https://drpc.org/chainlist/0g-galileo-testnet-rpc ### Mainnet (Aristotle) **Explorer**: [https://explorer.0g.ai/mainnet/home](https://explorer.0g.ai/mainnet/home) | Parameter | Value | |-----------|-------| | **Network Name** | 0G Mainnet | | **Chain ID** | 16661 | | **Token Symbol** | 0G | | **RPC Endpoint** | https://evmrpc.0g.ai | | **Storage Indexer** | https://indexer-storage-turbo.0g.ai (API base URL; root `/` may return 404) | | **Block Explorer** | https://chainscan.0g.ai | | **Storage Start Block** | 2387557 | **Documentation**: [https://docs.0g.ai/developer-hub/mainnet/mainnet-overview](https://docs.0g.ai/developer-hub/mainnet/mainnet-overview) **Third-Party RPCs (Recommended for Production)**: - QuickNode: https://www.quicknode.com/chains/0g - ThirdWeb: https://thirdweb.com/0g-aristotle - Ankr: https://www.ankr.com/rpc/0g/ - dRPC: https://drpc.org/chainlist/0g-mainnet-rpc ## Smart Contract Addresses ### Testnet Contracts | Contract | Address | Purpose | |----------|---------|---------| | **Flow** | `0x22E03a6A89B950F1c82ec5e74F8eCa321a105296` | Storage data flow management | | **Mine** | `0x00A9E9604b0538e06b268Fb297Df333337f9593b` | Storage mining rewards | | **Reward** | `0xA97B57b4BdFEA2D0a25e535bd849ad4e6C440A69` | Reward distribution | | **DAEntrance** | not published; ask the DA team | DA blob submission. The previously documented testnet addresses have no code on Galileo, so none is listed here | | **DASigners** | `0x0000000000000000000000000000000000001000` | DA signer management (precompile) | | **WrappedOGBase** | `0x0000000000000000000000000000000000001002` | Wrapped native token (precompile) | | **Compute Ledger** | `0xE70830508dAc0A97e6c087c75f402f9Be669E406` | Compute network payment ledger | | **Compute Inference** | `0xa79F4c8311FF93C06b8CfB403690cc987c93F91E` | Compute inference service | | **Compute FineTuning** | `0xC6C075D8039763C8f1EbE580be5ADdf2fd6941bA` | Compute fine-tuning service (`fine-tuning-v1.1`) | The previous testnet fine-tuning contract (`0xaC66eBd174435c04F1449BBa08157a707B6fa7b1`, registered as `fine-tuning-v1.0`) is still deployed and still registered on the Ledger, but it runs an older ABI. Use `fine-tuning-v1.1` for new integrations; historical indexers covering data before 2026-02-12 still need the old address. ### Mainnet Contracts | Contract | Address | Purpose | |----------|---------|---------| | **Flow** | `0x62D4144dB0F0a6fBBaeb6296c785C71B3D57C526` | Storage data flow management | | **Mine** | `0xCd01c5Cd953971CE4C2c9bFb95610236a7F414fe` | Storage mining rewards | | **Reward** | `0x457aC76B58ffcDc118AABD6DbC63ff9072880870` | Reward distribution | | **DASigners** | `0x0000000000000000000000000000000000001000` | DA signer management (precompile) | | **WrappedOGBase** | `0x0000000000000000000000000000000000001002` | Wrapped native token (precompile) | | **Compute Ledger** | `0x2dE54c845Cd948B72D2e32e39586fe89607074E3` | Compute network payment ledger | | **Compute Inference** | `0x47340d900bdFec2BD393c626E12ea0656F938d84` | Compute inference service | | **Compute FineTuning** | `0x4e3474095518883744ddf135b7E0A23301c7F9c0` | Compute fine-tuning service | ### $0G Token Contracts $0G is the **native gas token** on 0G Mainnet (no contract address). Official token contract representations: | Network (chain ID) | Token | Address | |--------------------|-------|---------| | 0G Mainnet (16661) | W0G — Wrapped 0G | `0x1Cd0690fF9a693f5EF2dD976660a8dAFc81A109c` | | Ethereum (1) | 0G — official bridged token | `0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE` | | BNB Chain (56) | 0G — official bridged token | `0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE` | All 18 decimals. The bridged token shares the same address on Ethereum and BNB Chain (bridged via Stargate). Any other contract claiming to be $0G is not official. ## 0G Services Overview ### 0G Chain **Documentation**: [https://docs.0g.ai/concepts/chain](https://docs.0g.ai/concepts/chain) AI-native EVM L1 chain with 11,000 TPS per Shard, sub-second finality, and full EVM compatibility. **Key Features**: - **Full EVM compatibility** - Use existing Ethereum tools (Hardhat, Foundry, Remix) - **11,000 TPS per Shard** with sub-second finality - **Same as Ethereum development** - just different RPC endpoint - Optimized CometBFT consensus - Native precompiled contracts for DA and wrapped tokens **Deploy Smart Contracts**: Using Hardhat: ```javascript // hardhat.config.js module.exports = { networks: { testnet: { url: "https://evmrpc-testnet.0g.ai", chainId: 16602, accounts: ["YOUR_PRIVATE_KEY"] }, mainnet: { url: "https://evmrpc.0g.ai", chainId: 16661, accounts: ["YOUR_PRIVATE_KEY"] } }, solidity: "0.8.20" }; ``` Using Foundry: ```bash # Testnet forge create --rpc-url https://evmrpc-testnet.0g.ai \ --private-key YOUR_PRIVATE_KEY \ src/MyContract.sol:MyContract # Mainnet forge create --rpc-url https://evmrpc.0g.ai \ --private-key YOUR_PRIVATE_KEY \ src/MyContract.sol:MyContract ``` Using Remix: 1. Open Remix IDE 2. Compile your contract 3. Go to Deploy & Run Transactions 4. Select "Injected Provider - MetaMask" 5. Ensure MetaMask is connected to 0G network 6. Deploy! **Precompiled Contracts**: DASigners (0x0000000000000000000000000000000000001000): ```solidity // Query DA signers, quorums and epochs function epochNumber() external view returns (uint); function quorumCount(uint _epoch) external view returns (uint); function isSigner(address _account) external view returns (bool); function getSigner(address[] memory _account) external view returns (SignerDetail[] memory); function getQuorum(uint _epoch, uint _quorumId) external view returns (address[] memory); function getQuorumRow(uint _epoch, uint _quorumId, uint32 _rowIndex) external view returns (address); function registeredEpoch(address _account, uint _epoch) external view returns (bool); ``` WrappedOGBase (0x0000000000000000000000000000000000001002): ```solidity // Quota-based wrapper for native 0G; not a WETH-style deposit/withdraw interface. struct Supply { uint256 cap; // maximum allowed mint supply for the minter uint256 initialSupply; // initial mint supply, also the initial allowed burn amount uint256 supply; // current mint supply used by the minter } function getWA0GI() external view returns (address); function minterSupply(address minter) external view returns (Supply memory); function mint(address minter, uint256 amount) external; // only callable by the WA0GI contract function burn(address minter, uint256 amount) external; // only callable by the WA0GI contract ``` **Verification & Indexing**: - **Goldsky**: GraphQL indexing and real-time data streaming - Docs: https://docs.goldsky.com/chains/0g - Guide: [https://docs.0g.ai/developer-hub/building-on-0g/indexing/goldsky](https://docs.0g.ai/developer-hub/building-on-0g/indexing/goldsky) **Documentation Links**: - Deploy Contracts: [https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts](https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) - Precompiles: [https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/precompiles/overview](https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/precompiles/overview) - Staking: [https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/staking-interfaces](https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/staking-interfaces) - Validator Contracts: [https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/validator-contract-functions](https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/validator-contract-functions) ### 0G Storage **Documentation**: [https://docs.0g.ai/concepts/storage](https://docs.0g.ai/concepts/storage) Decentralized storage offering 95% lower costs than AWS with instant retrieval. **Key Features**: - 95% cheaper than centralized alternatives - 200 MBPS retrieval speed - Proven TB-scale operations - Two storage layers: Log (immutable) + KV (mutable) - Proof of Random Access (PoRA) consensus **Flow Contract Note**: The Flow contract (`log_contract_address`) manages on-chain data flow for storage operations. For **TypeScript SDK file uploads**, the flow contract is handled internally by the Indexer — you only need the EVM RPC URL. For **KV operations**, the flow contract address is still required when constructing a `Batcher`. For **Go SDK**, the indexer client also handles flow contract interaction internally. The flow contract addresses are listed in the contract tables above. **SDK Installation**: TypeScript/JavaScript: ```bash npm install @0gfoundation/0g-storage-ts-sdk ethers ``` Go: ```bash go get github.com/0gfoundation/0g-storage-client ``` **Starter Kits** (recommended for getting started quickly): - TypeScript: https://github.com/0gfoundation/0g-storage-ts-starter-kit — CLI scripts (`npm run upload`), importable library (`uploadFile`, `downloadFile`, `uploadData`, `batchUpload`), and browser UI with MetaMask. Supports turbo/standard storage modes. - Go: https://github.com/0gfoundation/0g-storage-go-starter-kit **Quick Start Examples**: TypeScript - Upload File: ```typescript import { ZgFile, Indexer } from "@0gfoundation/0g-storage-ts-sdk"; import { ethers } from "ethers"; const provider = new ethers.JsonRpcProvider("https://evmrpc-testnet.0g.ai"); const signer = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const indexer = new Indexer("https://indexer-storage-testnet-turbo.0g.ai"); // Upload — flow contract is resolved internally by the Indexer const file = await ZgFile.fromFilePath("/path/to/file"); const [tree, treeErr] = await file.merkleTree(); console.log("Root Hash:", tree?.rootHash()); const [tx, uploadErr] = await indexer.upload(file, "https://evmrpc-testnet.0g.ai", signer); await file.close(); ``` TypeScript - KV Operations (requires flow contract): ```typescript import { Batcher, KvClient } from "@0gfoundation/0g-storage-ts-sdk"; // KV upload needs the flow contract address const batcher = new Batcher(1, nodes, flowContract, RPC_URL); batcher.streamDataBuilder.set(streamId, keyBytes, valueBytes); const [tx, err] = await batcher.exec(); // KV read const kvClient = new KvClient(""); const value = await kvClient.getValue(streamId, encodedKey); ``` **CLI Tool** (Go — built from 0g-storage-client): ```bash # Install git clone https://github.com/0gfoundation/0g-storage-client.git cd 0g-storage-client go build # Upload file 0g-storage-client upload \ --url https://evmrpc-testnet.0g.ai \ --key YOUR_PRIVATE_KEY \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --file /path/to/file # Upload with client-side encryption (AES-256-CTR) 0g-storage-client upload \ --url https://evmrpc-testnet.0g.ai \ --key YOUR_PRIVATE_KEY \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --file /path/to/file \ --encryption-key # Download file (--proof enables merkle verification) 0g-storage-client download \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --root \ --file output.dat \ --proof # KV write 0g-storage-client kv-write \ --url https://evmrpc-testnet.0g.ai \ --key YOUR_PRIVATE_KEY \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --stream-id \ --stream-keys \ --stream-values # KV read 0g-storage-client kv-read \ --node \ --stream-id \ --stream-keys ``` **Indexer REST API** (HTTP gateway for file operations): ```text GET /file?root=0x... # Download file by merkle root GET /file?txSeq=7 # Download file by tx sequence GET /file/{root}/path/to/file # Download file from folder GET /file/info/{cid} # Query file info POST /file/segment # Upload file segment (JSON: txSeq/root, index, data, proof) ``` The storage indexer URLs above are API base URLs. The root path (`/`) is not a health endpoint and can return `404`; use an API route such as `/file/info/{cid}` when checking indexer availability. **Documentation Links**: - SDK Guide: [https://docs.0g.ai/developer-hub/building-on-0g/storage/sdk](https://docs.0g.ai/developer-hub/building-on-0g/storage/sdk) - CLI Guide: [https://docs.0g.ai/developer-hub/building-on-0g/storage/storage-cli](https://docs.0g.ai/developer-hub/building-on-0g/storage/storage-cli) **GitHub Repositories**: - Storage Node: https://github.com/0gfoundation/0g-storage-node - Storage KV: https://github.com/0gfoundation/0g-storage-kv - Go Client/CLI: https://github.com/0gfoundation/0g-storage-client - TypeScript SDK: https://github.com/0gfoundation/0g-storage-ts-sdk ### 0G Compute **Documentation**: [https://docs.0g.ai/concepts/compute](https://docs.0g.ai/concepts/compute) Decentralized GPU marketplace offering 90% cheaper AI workloads with OpenAI SDK compatibility. **Key Features**: - 90% cost reduction vs traditional cloud (e.g., $0.003 vs $0.03 per 1K tokens) - Pay-per-use pricing (no subscriptions or monthly minimums) - OpenAI SDK compatible - drop-in replacement - Smart contract escrow for trustless payments - TEE (Trusted Execution Environment) for secure processing - 50-100ms inference latency - Supports: Chatbot (LLM), Text-to-Image, Speech-to-Text **DePIN Partners**: - **io.net**: 300,000+ GPUs across 139 countries - **Aethir**: 43,000+ enterprise-grade GPUs, 3,000+ H100s/H200s **Two Integration Paths**: 1. **Router (recommended)** — a single OpenAI-compatible API endpoint (`https://router-api.0g.ai/v1`) with one unified balance, automatic provider failover, and an API key. Best for server-side apps, agents, prototypes. Web UI: [pc.0g.ai](https://pc.0g.ai). 2. **Direct** — connect to individual providers via the `@0gfoundation/0g-compute-ts-sdk` SDK, manage per-provider sub-accounts, sign each request with your wallet. Best for browser dApps with wallet signing or direct on-chain control. Web UI: [compute-marketplace.0g.ai](https://compute-marketplace.0g.ai) (or **Advanced** mode on pc.0g.ai). The two balance pools are independent — a Router deposit does not fund Direct sub-accounts and vice versa. **Quick Start — Router (Recommended)**: ```bash # 1. Visit https://pc.0g.ai, connect wallet, deposit 0G tokens # 2. Dashboard → API Keys → create a key with 'inference' permission (starts with sk-) # 3. Send a request — any OpenAI-compatible client works: curl https://router-api.0g.ai/v1/chat/completions \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello!"}] }' ``` **OpenAI SDK Integration (Router)**: ```python from openai import OpenAI client = OpenAI( base_url="https://router-api.0g.ai/v1", api_key="sk-YOUR_API_KEY" ) response = client.chat.completions.create( model="glm-5.2", messages=[{"role": "user", "content": "Hello!"}] ) ``` **Router also supports**: image generation via `POST /v1/images/generations` (OpenAI-compatible, sync) or `POST /v1/async/images/generations` + `GET /v1/async/jobs/{jobId}?provider_address=...` (recommended for production) — both paths must pass `"response_format": "b64_json"` today; URL responses will be added later. Also `/v1/audio/transcriptions`, provider routing via `X-0G-Provider-*` request headers (`X-0G-Provider-Sort: latency`/`price`, `X-0G-Provider-Address: 0x…` to pin, or `X-0G-Provider-Max-Price-Usd-Prompt`/`-Completion`/`-Image` to cap per-request price — header-only, malformed values return `400`), `GET /v1/models` (no auth), `GET /v1/account/balance`, `GET /v1/account/usage/{stats,history}`. The Router also serves the **Anthropic Messages API** (`POST /v1/messages`): set `ANTHROPIC_BASE_URL=https://router-api.0g.ai` to point Anthropic SDKs or Claude Code at it; models listing `"anthropic"` in `supported_formats` on `GET /v1/models` support this format. **Quick Start — Direct (SDK)**: ```bash # Install CLI pnpm add @0gfoundation/0g-compute-ts-sdk -g # Setup + fund 0g-compute-cli setup-network 0g-compute-cli login # prompts for wallet private key 0g-compute-cli deposit --amount 10 0g-compute-cli inference list-providers 0g-compute-cli transfer-fund --provider --amount 5 # auto-acknowledges # Get a per-provider secret key 0g-compute-cli inference get-secret --provider ``` With the per-provider secret, you call the provider's proxy directly: ```python from openai import OpenAI client = OpenAI( base_url="/v1/proxy", api_key="app-sk-", ) ``` **Fine-tuning Models** (uses the Direct account system; not available via Router): ```bash # Prepare dataset (JSONL format, one {"prompt": "...", "completion": "..."} per line) 0g-compute-cli fine-tuning upload-data --file dataset.jsonl # Create fine-tuning task (fund the fine-tuning sub-account first: transfer-fund --service fine-tuning) 0g-compute-cli fine-tuning create-task \ --model Qwen2.5-0.5B-Instruct \ --dataset \ --provider # Monitor progress 0g-compute-cli fine-tuning get-task --task-id ``` **Documentation Links**: - Overview: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/overview](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/overview) - Router (recommended): - Overview: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/overview](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/overview) - Quickstart: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/quickstart](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/quickstart) - Models: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/models](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/models) - Chat Completions: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/chat-completions](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/chat-completions) - Claude Code (Anthropic API): [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/clients/claude-code](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/clients/claude-code) - Provider Routing: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/routing](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/routing) - Deposits & Billing: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/account/deposits](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/account/deposits) - Router vs Direct: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/comparison](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/comparison) - Direct (SDK): - Inference: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference) - Account: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/account-management](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/account-management) - Fine-tuning: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/fine-tuning](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/fine-tuning) - Provider Setup: [https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference-provider](https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference-provider) ### 0G DA (Data Availability) **Documentation**: [https://docs.0g.ai/concepts/da](https://docs.0g.ai/concepts/da) Scalable data availability layer for rollups with 50 Gbps throughput. **Key Features**: - 50 Gbps demonstrated throughput - VRF-based node selection - Inherits Ethereum security **For Rollup Developers**: - OP Stack Integration: [https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/op-stack-on-0g-da](https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/op-stack-on-0g-da) - Repo: https://github.com/0gfoundation/0g-da-op-plasma - Arbitrum Nitro: [https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/arbitrum-nitro-on-0g-da](https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/arbitrum-nitro-on-0g-da) - Repo: https://github.com/0gfoundation/nitro - Integration Guide: [https://docs.0g.ai/developer-hub/building-on-0g/da-integration](https://docs.0g.ai/developer-hub/building-on-0g/da-integration) ### Agentic ID (formerly INFT) **Documentation**: [https://docs.0g.ai/concepts/agentic-id](https://docs.0g.ai/concepts/agentic-id) Agentic ID is the rebrand of what was previously called INFT (Intelligent NFT). ERC-7857 is the underlying NFT standard for tokenizing AI agents. It extends ERC-721 with encrypted metadata, secure re-encryption on transfer via TEE/ZKP oracles, cloning, and usage authorization. The reference implementation uses upgradeable beacon proxies and OpenZeppelin AccessControl. 0G also officially supports **ERC-8004** (Trustless Agents) for public on-chain agent identity and discoverability, and Agentic ID is ERC-8004 compatible (see the ERC-8004 section below). **GitHub Repository**: https://github.com/0gfoundation/0g-agent-nft **Core Interface (IERC7857)**: ```solidity interface IERC7857 is IERC721, IERC7857Metadata { // Transfer token with encrypted metadata re-encryption function iTransferFrom( address _from, address _to, uint256 _tokenId, TransferValidityProof[] calldata _proofs ) external; // Delegate access-proof signing to an assistant address function delegateAccess(address _assistant) external; // Get the verifier contract (TEE or ZKP oracle) function verifier() external view returns (IERC7857DataVerifier); } ``` **Key Data Structures**: ```solidity struct IntelligentData { string dataDescription; bytes32 dataHash; } struct TransferValidityProof { AccessProof accessProof; // Signed by receiver OwnershipProof ownershipProof; // Signed by TEE/ZKP oracle } struct OwnershipProof { OracleType oracleType; // TEE or ZKP bytes32 dataHash; bytes sealedKey; // Encryption key sealed for receiver bytes targetPubkey; bytes nonce; bytes proof; } enum OracleType { TEE, ZKP } ``` **Extensions**: - **Cloneable** (`IERC7857Cloneable`): `iCloneFrom()` — creates a new token with the same encrypted metadata - **Authorize** (`IERC7857Authorize`): `authorizeUsage()` / `revokeAuthorization()` — grant usage rights without ownership transfer (max 100 users per token, cleared on transfer) - **Data Storage** (`ERC7857IDataStorageUpgradeable`): On-chain storage for arrays of `IntelligentData` per token **Architecture**: - **AgentNFT**: Main contract — minting, creator tracking, mint fees. Roles: `ADMIN_ROLE`, `OPERATOR_ROLE`, `MINTER_ROLE` - **Verifier**: Orchestrates TEE/ZKP proof verification with replay protection (nonce-based, 7-day expiry) - **TeeVerifier**: ECDSA signature verification against a registered TEE oracle address - **AgentMarket**: Marketplace with order/offer model, EIP-712 signatures, platform + partner fee distribution, and native/ERC20 payment support **Transfer Flow**: 1. Receiver signs `AccessProof` (proving they want the data) 2. TEE/ZKP oracle decrypts metadata, re-encrypts with receiver's public key, produces `OwnershipProof` with `sealedKey` 3. `iTransferFrom()` calls `verifier.verifyTransferValidity()` to validate both proofs 4. Token ownership transfers and `PublishedSealedKey` event emits for receiver to decrypt **Use Cases**: AI Trading Bots, Personal Assistants, Game Characters, Content Creation AI, Research Tools **Documentation Links**: - Agentic ID Overview: [https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/overview](https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/overview) - ERC-7857 Standard: [https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc7857](https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc7857) - Integration Guide: [https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/integration](https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/integration) **ERC-8004 Support**: 0G officially supports **ERC-8004** (Trustless Agents), the standard for on-chain agent identity, discoverability, and reputation. 0G's ERC-8004 registry deployment is listed in the official standard repo ([erc-8004/erc-8004-contracts](https://github.com/erc-8004/erc-8004-contracts)). Agentic ID is ERC-8004 compatible — an Agentic ID can carry a corresponding ERC-8004 registration. Registered agents are discoverable at [8004scan.io](https://8004scan.io). **Registry Addresses**: - 0G Mainnet (chain ID 16661): IdentityRegistry `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`, ReputationRegistry `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` (explorer: chainscan.0g.ai) - 0G Galileo Testnet (chain ID 16602): IdentityRegistry `0x8004A818BFB912233c491871b3d84c89A494BD9e`, ReputationRegistry `0x8004B663056A597Dffe9eCcC1965A193B7388713` (explorer: chainscan-galileo.0g.ai) **ERC-8004 Guide**: [https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc8004](https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc8004) ## Developer Tools ### Indexing with Goldsky **Website**: https://docs.goldsky.com/chains/0g **Products**: - **Subgraphs**: GraphQL indexing for smart contracts - **Mirror**: Real-time data streaming to databases **Documentation**: [https://docs.0g.ai/developer-hub/building-on-0g/indexing/goldsky](https://docs.0g.ai/developer-hub/building-on-0g/indexing/goldsky) ### Rollup-as-a-Service **Caldera on 0G DA**: [https://docs.0g.ai/developer-hub/building-on-0g/rollup-as-a-service/caldera-on-0g-da](https://docs.0g.ai/developer-hub/building-on-0g/rollup-as-a-service/caldera-on-0g-da) ### Smart Contract Development **Deploy with Hardhat**: ```javascript // hardhat.config.js module.exports = { networks: { testnet: { url: "https://evmrpc-testnet.0g.ai", chainId: 16602, accounts: ["YOUR_PRIVATE_KEY"] }, mainnet: { url: "https://evmrpc.0g.ai", chainId: 16661, accounts: ["YOUR_PRIVATE_KEY"] } } }; ``` **Deploy with Foundry**: ```bash # Testnet forge create --rpc-url https://evmrpc-testnet.0g.ai \ --private-key YOUR_PRIVATE_KEY \ src/MyContract.sol:MyContract # Mainnet forge create --rpc-url https://evmrpc.0g.ai \ --private-key YOUR_PRIVATE_KEY \ src/MyContract.sol:MyContract ``` **Documentation**: [https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts](https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) ## Key Concepts ### AI Alignment **Documentation**: [https://docs.0g.ai/concepts/ai-alignment](https://docs.0g.ai/concepts/ai-alignment) Monitor AI systems for proper behavior, safety, and alignment with human values. **Functions**: - Track model drift - Verify outputs - Monitor performance - Flag anomalies ### DePIN (Decentralized Physical Infrastructure) **Documentation**: [https://docs.0g.ai/concepts/depin](https://docs.0g.ai/concepts/depin) Physical GPU infrastructure provided by decentralized partners. **Partners**: - **io.net**: 300,000+ verified GPUs, 139 countries, 90% cost savings - **Aethir**: 43,000+ enterprise GPUs, 3,000+ H100s/H200s, 99.99% uptime ## Starter Kits & Examples ### Compute Starter Kit **Quick Start (Recommended for Hackathons)**: ```bash # Install global CLI pnpm add @0gfoundation/0g-compute-ts-sdk -g # Option 1: Web UI (fastest way to start) 0g-compute-cli ui start-web # Open http://localhost:3090, connect wallet, start using AI # Option 2: CLI for automation 0g-compute-cli setup-network # Choose testnet/mainnet 0g-compute-cli login # Connect your wallet 0g-compute-cli deposit --amount 10 # Fund account 0g-compute-cli inference list-providers # See available services ``` **OpenAI SDK Drop-in Replacement**: ```python from openai import OpenAI # Just change base_url and api_key! client = OpenAI( api_key="app-sk-", base_url="/v1/proxy" ) # Same API as OpenAI response = client.chat.completions.create( model="", messages=[{"role": "user", "content": "Hello!"}] ) ``` ### Storage Starter Kit **TypeScript Example**: ```bash npm install @0gfoundation/0g-storage-ts-sdk ethers ``` ```typescript import { ZgFile, Indexer } from "@0gfoundation/0g-storage-ts-sdk"; import { ethers } from "ethers"; const provider = new ethers.JsonRpcProvider("https://evmrpc-testnet.0g.ai"); const signer = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); const indexer = new Indexer("https://indexer-storage-testnet-turbo.0g.ai"); // Upload file — flow contract handled internally by Indexer const file = await ZgFile.fromFilePath("/path/to/file"); const [tree, treeErr] = await file.merkleTree(); console.log("Root Hash:", tree?.rootHash()); const [tx, uploadErr] = await indexer.upload(file, "https://evmrpc-testnet.0g.ai", signer); await file.close(); // Download file (withProof=true enables merkle verification) const err = await indexer.download(rootHash, "/path/to/output", true); ``` **Go Example**: ```bash go get github.com/0gfoundation/0g-storage-client ``` ```go import ( "github.com/0gfoundation/0g-storage-client/common/blockchain" "github.com/0gfoundation/0g-storage-client/indexer" "github.com/0gfoundation/0g-storage-client/transfer" "github.com/0gfoundation/0g-storage-client/core" ) // Initialize clients w3client := blockchain.MustNewWeb3(evmRpc, privateKey) defer w3client.Close() indexerClient, _ := indexer.NewClient(indexerRpc, indexer.IndexerClientOption{}) // Upload — flow contract handled internally by indexer file, _ := core.Open(filePath) defer file.Close() opt := transfer.UploadOption{ExpectedReplica: 1, FastMode: true} txHashes, roots, _ := indexerClient.SplitableUpload(ctx, w3client, file, 4*1024*1024*1024, opt) // Download indexerClient.Download(ctx, rootHash, outputPath, true) ``` ### Chain/Smart Contract Starter Kit **Hardhat Project**: ```bash npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox npx hardhat init ``` ```javascript // hardhat.config.js require("@nomicfoundation/hardhat-toolbox"); module.exports = { solidity: "0.8.20", networks: { testnet: { url: "https://evmrpc-testnet.0g.ai", chainId: 16602, accounts: [process.env.PRIVATE_KEY] } } }; ``` ```bash npx hardhat compile npx hardhat run scripts/deploy.js --network testnet ``` **Foundry Project**: ```bash forge init my-project cd my-project ``` ```bash # Deploy forge create --rpc-url https://evmrpc-testnet.0g.ai \ --private-key $PRIVATE_KEY \ src/Counter.sol:Counter # Verify interaction cast call "number()" --rpc-url https://evmrpc-testnet.0g.ai ``` ### SDK Examples - TypeScript SDK: https://github.com/0gfoundation/0g-storage-ts-sdk/tree/main/examples - Go SDK: https://github.com/0gfoundation/0g-storage-client/tree/main/examples ### Community Projects **Awesome 0G Repository**: https://github.com/0gfoundation/awesome-0g Curated list of community projects, tools, and resources built on 0G. ## Quick Reference ### Add Network to MetaMask **Testnet**: ```javascript await window.ethereum.request({ method: 'wallet_addEthereumChain', params: [{ chainId: '0x40DA', chainName: '0G Galileo Testnet', nativeCurrency: { name: '0G', symbol: '0G', decimals: 18 }, rpcUrls: ['https://evmrpc-testnet.0g.ai'], blockExplorerUrls: ['https://chainscan-galileo.0g.ai'] }] }); ``` **Mainnet**: ```javascript await window.ethereum.request({ method: 'wallet_addEthereumChain', params: [{ chainId: '0x4115', chainName: '0G Mainnet', nativeCurrency: { name: '0G', symbol: '0G', decimals: 18 }, rpcUrls: ['https://evmrpc.0g.ai'], blockExplorerUrls: ['https://chainscan.0g.ai'] }] }); ``` ### Common Commands **Storage Upload (CLI)**: ```bash 0g-storage-client upload \ --url https://evmrpc-testnet.0g.ai \ --key YOUR_PRIVATE_KEY \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --file /path/to/file ``` **Storage Download (CLI)**: ```bash 0g-storage-client download \ --indexer https://indexer-storage-testnet-turbo.0g.ai \ --root ROOT_HASH \ --file output.dat ``` ## Community & Support ### Official Links - **Documentation**: https://docs.0g.ai - **Website**: https://0g.ai - **GitHub**: https://github.com/0gfoundation - **Discord**: https://discord.gg/0gLabs - **Twitter/X**: https://x.com/0g_Labs ### Getting Help - Documentation: [https://docs.0g.ai/developer-hub/getting-started](https://docs.0g.ai/developer-hub/getting-started) - Discord Developer Channel: https://discord.gg/0gLabs - GitHub Issues: Create issues in respective repositories ## Vision & Mission **Mission**: Make AI a Public Good **Vision**: Democratized, transparent, fair, and secure AI infrastructure **Approach**: - Open infrastructure - Community ownership - Economic alignment - Technical excellence **Documentation**: [https://docs.0g.ai/introduction/vision-mission](https://docs.0g.ai/introduction/vision-mission) --- ## Additional Resources ### Security **Documentation**: [https://docs.0g.ai/resources/security](https://docs.0g.ai/resources/security) ### Contributing **Documentation**: [https://docs.0g.ai/resources/how-to-contribute](https://docs.0g.ai/resources/how-to-contribute) ### Glossary **Documentation**: [https://docs.0g.ai/resources/glossary](https://docs.0g.ai/resources/glossary) --- *Last verified: 2026-09-02 (see the ai-context-review workflow for automated drift checks). This context page gives AI coding assistants comprehensive information about 0G infrastructure. All information is sourced from official documentation at https://docs.0g.ai.* --- ## Agentic ID Source: https://docs.0g.ai/concepts/agentic-id.md :::info Previously known as INFTs Agentic ID is the new name for what was previously called an **INFT** (Intelligent NFT). Same standard (ERC-7857), same encrypted-metadata transfer model. ::: Traditional NFTs can't handle AI agents. When you "own" an AI agent NFT today, you only own a pointer to some metadata - not the actual intelligence. The AI doesn't transfer with the NFT. ## What are Agentic IDs? **Agentic IDs** (formerly Intelligent NFTs) solve this problem. They're a new type of NFT specifically designed to tokenize AI agents with their complete intelligence intact.
New to AI tokenization? Traditional approach: - NFT points to AI metadata stored somewhere - When you buy the NFT, you don't get the actual AI - The intelligence stays with the original creator - You can't actually use the AI agent Agentic ID approach: - NFT contains encrypted AI intelligence - When transferred, the AI moves with it - New owner gets full access to the AI agent - Complete ownership of AI capabilities
## Why Agentic IDs Matter ### True AI Ownership Unlike regular NFTs that just point to metadata, Agentic IDs contain the actual AI agent. When you own an Agentic ID, you own the complete intelligence, not just a certificate. ### Privacy-First Design AI agents often contain sensitive data or proprietary algorithms. Agentic IDs keep this data encrypted throughout the entire lifecycle - only the owner can access it. ### Secure Transfers When an Agentic ID changes hands, both the ownership AND the encrypted AI intelligence transfer together. The new owner gets a fully functional AI agent. ### Decentralized Storage Agentic IDs leverage 0G Storage to keep AI agents permanently available without relying on centralized servers that could go offline. ## Real-World Use Cases | Use Case | How Agentic IDs Help | Example | |----------|---------------|---------| | **AI Trading Bots** | Own and transfer profitable trading strategies | DeFi trading bot with proven track record | | **Personal Assistants** | Trained AI agents that know your preferences | AI that learned your workflow and habits | | **Game Characters** | Intelligent NPCs with unique personalities | AI companion that evolved through gameplay | | **Content Creation** | AI models trained for specific styles | AI artist trained on your creative style | | **Research Tools** | Specialized AI for domain-specific tasks | Medical AI trained on specific datasets | ## How It Works 1. **Create**: Build and train your AI agent 2. **Encrypt**: Secure the AI's intelligence with encryption 3. **Mint**: Create an Agentic ID containing the encrypted AI 4. **Own**: Have complete ownership and control over the AI agent ## Technical Foundation Agentic IDs are built on **ERC-7857**, a new NFT standard that extends ERC-721 with: - **Encrypted metadata storage** for protecting AI intelligence - **Secure re-encryption** for safe ownership transfers - **Oracle verification** to ensure transfer integrity - **Authorized usage** for AI-as-a-Service models ## ERC-8004 Compatibility Agentic IDs are compatible with **ERC-8004**, the Trustless Agent standard that 0G officially supports. An Agentic ID can carry a corresponding ERC-8004 registration, making the agent discoverable and interoperable across the ERC-8004 ecosystem. Learn more in the **[ERC-8004 guide](../developer-hub/building-on-0g/agentic-id/erc8004)**. ## Powered by 0G Agentic IDs leverage the complete 0G ecosystem: | Component | Role | Benefit | |-----------|------|---------| | **0G Storage** | Encrypted AI storage | Permanent, decentralized availability | | **0G Chain** | Smart contract execution | Fast, low-cost Agentic ID operations | | **0G Compute** | Secure AI inference | Private execution environment | | **0G DA** | Transfer verification | Guaranteed data availability | ## Getting Started ### For AI Developers Transform your AI agents into tradeable assets while maintaining privacy and control. **[Build Agentic IDs](../developer-hub/building-on-0g/agentic-id/overview)** - Complete development guide --- :::tip Next Steps Ready to dive deeper? Check out the **[complete Agentic ID documentation](../developer-hub/building-on-0g/agentic-id/overview)** for technical details, implementation guides, and real-world examples. ::: --- ## AI Alignment Nodes Source: https://docs.0g.ai/concepts/ai-alignment.md ## What are AI Alignment Nodes? AI Alignment Nodes are specialized network participants that monitor and ensure the proper behavior of AI systems and network protocols within the 0G ecosystem. They serve as the guardians of network integrity, verifying that all components operate according to their intended specifications. :::success **Why AI Alignment Matters** As AI becomes more powerful, ensuring it remains aligned with human values and operates safely becomes critical 🛡️ ::: ## The Problem with Centralized AI Traditional AI systems face several alignment challenges: - **Lack of Transparency**: Black box operations with no external oversight - **Single Point of Control**: Centralized entities make all decisions about AI behavior - **Limited Accountability**: No mechanism for community oversight or intervention - **Potential for Misalignment**: AI systems may drift from their intended purpose without detection ## How AI Alignment Nodes Work ### AI Model Monitoring As 0G's on-chain AI capabilities expand, Alignment Nodes will: - **Track Model Drift**: Detect when AI models deviate from expected behavior - **Verify Outputs**: Ensure AI-generated results meet quality and safety standards - **Monitor Performance**: Track AI system efficiency and accuracy over time - **Flag Anomalies**: Alert the network to unusual or potentially harmful AI behavior ### Network Security Alignment Nodes contribute to overall network security by: - **Identifying Protocol Violations**: Detecting when nodes fail to follow network rules - **Reporting Malicious Behavior**: Flagging potential attacks or bad actors - **Maintaining Ethical Standards**: Ensuring AI operations align with community values - **Supporting Governance**: Providing data for network governance decisions ## The Future of Decentralized AI Safety AI Alignment Nodes represent a critical innovation in ensuring that decentralized AI systems remain safe, transparent, and aligned with human values. As AI capabilities expand, these nodes will become increasingly important for: ### Scalable Oversight - **Automated Monitoring**: AI-powered oversight that scales with network growth - **Distributed Governance**: Community-driven decisions about AI behavior - **Continuous Learning**: Alignment systems that improve over time - **Global Participation**: Worldwide network of AI safety monitors ### Innovation Enablement By providing robust safety guarantees, Alignment Nodes enable: - **Faster AI Development**: Developers can build with confidence in safety systems - **Greater Public Trust**: Transparent oversight builds user confidence - **Regulatory Compliance**: Meeting emerging AI safety regulations - **Ecosystem Growth**: Safe AI attracts more users and developers ## Getting Started Interested in contributing to AI safety through Alignment Nodes? - [AI Alignment Node ](/node-sale/intro) - Learn more about the AI Alignment Node. --- *Building safe AI for everyone, together.* --- ## 0G Chain Source: https://docs.0g.ai/concepts/chain.md ## The Problem with AI on Blockchain Try running an AI model on Ethereum today: - **Cost**: $1M+ in gas fees for a simple model - **Speed**: 15 transactions per second (AI needs thousands) - **Data**: Can't handle AI's massive data requirements ## What is 0G Chain? 0G Chain is a blockchain built specifically for AI applications. Think of it as Ethereum, but optimized for AI workloads with significantly higher throughput. :::success **EVM Compatibility** Your existing Ethereum code works without changes 🤝 ::: ## How 0G Chain Works ### Modular Architecture 0G Chain features an advanced modular design that distinctly separates consensus from execution. This separation into independent, yet interconnected, layers is a cornerstone of 0G Chain's architecture, delivering enhanced flexibility, scalability, and a faster pace of innovation. **Architecture Overview**: - **Consensus Layer**: Dedicated to achieving network agreement. It manages validator coordination, block production, and ensures the overall security and finality of the chain. - **Execution Layer**: Focused on state management. It handles smart contract execution, processes transactions, and maintains compatibility with the EVM (Ethereum Virtual Machine). **Key Technical Advantages**: - **Independent Upgradability**: The execution layer can rapidly incorporate new EVM features (such as EIP-4844, account abstraction, or novel opcodes) without requiring changes to the underlying consensus mechanism. - **Focused Optimization**: Conversely, the consensus layer can be upgraded with critical performance or security enhancements without impacting the EVM or ongoing execution processes. - **Accelerated Development**: This decoupling allows for parallel development and faster iteration cycles for both layers, leading to quicker adoption of new technologies and improvements in both performance and features. This design makes 0G Chain flexible and fast. When new blockchain features come out, we can add them quickly without breaking anything. This keeps 0G optimized for AI while staying up-to-date with the latest technology. ### Optimized Consensus 0G Chain employs a highly optimized version of CometBFT (formerly Tendermint) as its consensus mechanism, with meticulously tuned parameters that achieve maximum performance while maintaining security. The system features carefully calibrated block production intervals and timeout configurations that work together to deliver high throughput, ensure network stability, and enable faster consensus rounds—all without compromising the fundamental safety guarantees. These optimizations enable 0G Chain to achieve maximum performance: - **11,000 TPS per Shard**: Current throughput significantly exceeds traditional blockchain networks - **Sub-second Finality**: Near-instant transaction confirmation for AI applications - **Consistent Performance**: Maintains high throughput even under heavy network load ### Scaling Roadmap - **DAG-Based Consensus**: Transitioning to Directed Acyclic Graph (DAG) based consensus for exponentially higher efficiency - Parallel transaction processing capabilities - Elimination of sequential block limitations - **Shared Security Model**: Implementing shared staking mechanisms to enhance network security - Validators can secure multiple services simultaneously - Increased capital efficiency for stakers ## Technical Deep Dive
**How does 0G achieve high throughput?** Currently achieves 11,000 TPS per Shard through: 1. **Optimized CometBFT**: Highly efficient consensus based on Tendermint 2. **Efficient block production**: Tuned for AI-scale data processing 3. **Fast finality**: Sub-second transaction confirmation **Future scaling** will add: - Multiple parallel consensus networks - Dynamic capacity expansion - Automatic load balancing
**How does the validator system work?** **Staking & Consensus**: - Validators stake 0G tokens to participate - CometBFT ensures Byzantine fault tolerance **Rewards**: - Block production rewards - Transaction fee collection - Staking yields proportional to stake size **Node Selection**: - VRF (Verifiable Random Function) for fair validator selection - Prevents collusion and ensures decentralization
**What makes 0G different from other fast chains?** Unlike general-purpose "fast" blockchains: - **AI-First Design**: Data structures optimized for AI workloads - **Modular Architecture**: Upgrade components independently - **EVM + More**: Start with Ethereum compatibility, expand to other VMs - **Purpose-Built**: Not retrofitted - designed from scratch for AI
0G Chain's modular architecture enables seamless integration with storage, compute, and DA layers ## Validator Participation Validators earn rewards through: - **Block rewards**: For producing valid blocks - **Transaction fees**: From network usage - **Staking rewards**: Based on stake size and uptime Validator reward and penalty structure in the 0G network ## Frequently Asked Questions
**Is 0G Chain truly decentralized?** Yes! 0G Chain operates with a permissionless, globally distributed validator set using proof-of-stake consensus. No single entity controls the network.
**Do I need to rewrite my Ethereum dApp?** No! Full EVM compatibility means your Solidity code deploys without changes. The only differences you'll notice are speed and cost improvements.
**Why is it faster than Ethereum?** 0G Chain is purpose-built for AI workloads, while Ethereum is general-purpose. We achieve speed through: - Optimized consensus mechanism (CometBFT) - AI-specific data structures - Focused use case optimization
## Next Steps Ready to build? Start here: - [Quick Start Guide](/developer-hub/getting-started) - Deploy in 5 minutes - [Migration from Ethereum](/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) - Move existing dApps - [Technical Whitepaper](/resources/whitepaper) - Deep architecture details --- *0G Chain: Where AI meets blockchain at scale.* --- ## 0G Compute Network Source: https://docs.0g.ai/concepts/compute.md In today's world, AI models are transforming industries, driving innovation, and powering new applications. However, running advanced AI models for your application faces several obstacles: - **High Costs**: Enterprise AI services require significant monthly commitments - **Complex Setup**: Cloud GPU configuration requires technical expertise - **Vendor Lock-in**: Limited flexibility when switching providers **The result?** AI computing remains inaccessible for many developers and startups. ## What is 0G Compute? 0G Compute is a decentralized framework that provides AI computing capabilities to our community. It forms a crucial part of the 0G stack. 0G Compute is a decentralized marketplace where GPU owners sell computing power to developers who need it - think Uber for AI computing. **Key difference**: Instead of renting from AWS/Google with high costs and lock-in, you access a global GPU network that's 90% cheaper with pay-per-use pricing. ## How It Works ### For AI Users 1. **Deposit Funds**: Pre-fund your account with pay-as-you-go credits 2. **Request Service**: Send your AI request (inference, training, etc.) 3. **Get Results**: Receive output from the best available GPU 4. **Automatic Payment**: Pay only for actual compute used ### For GPU Owners 1. **Register Hardware**: List your GPU specs and availability 2. **Set Your Price**: Competitive marketplace pricing 3. **Process Requests**: Automatic job allocation 4. **Instant Earnings**: Get paid immediately upon completion ### Technical Implementation - **Smart Contract Escrow**: Funds secured until service delivery - **Signed Transactions**: Cryptographic verification of all interactions - **ZK-Proof Settlement**: 100x lower transaction costs through compressed proofs
**What makes it trustless?** Like eBay with automatic escrow - the smart contract ensures: - Payment only after service delivery - Both parties must fulfill obligations - No intermediary can interfere This means no one can censor your AI usage, freeze your account, or change terms suddenly.
## Why Choose 0G Compute? ### 💰 Key Advantages | Feature | Traditional Cloud | 0G Compute | | ---------------- | ------------------- | ------------------ | | Pricing Model | Fixed monthly costs | Pay-per-use | | Provider Options | Limited vendors | Global GPU network | ### 🌐 Access From Anywhere - **Blockchains**: Direct integration with Ethereum, Solana, any chain - **Traditional Apps**: Simple REST API using 0G SDK ### 🔐 Your Data, Your Control - No data retention by providers - Verifiable computation proofs - Supports TEEML, OPML & ZKML ## Common Questions
**What about reliability?** Built-in redundancy: - Automatic failover to next provider - Thousands of providers globally
**Can I run proprietary models?** Yes. Upload any model, set requirements and pricing, and start serving requests. Perfect for specialized use cases.
**How does pricing work?** Pure pay-per-use: - No subscriptions - Competitive market-driven pricing - Transparent costs visible upfront
## Get Started ### 📚 Technical Deep Dive Architecture and implementation details → [Technical Documentation](/developer-hub/building-on-0g/compute-network/overview) ### 🚀 For Developers Start using AI compute in 5 minutes → [Quick Start Guide](/developer-hub/building-on-0g/compute-network/router/quickstart) ### 💎 For GPU Owners Turn idle hardware into income → [Become a Provider](/developer-hub/building-on-0g/compute-network/inference-provider) --- *0G Compute: Making AI accessible to everyone.* --- ## 0G DA Source: https://docs.0g.ai/concepts/da.md ## The Rise of Data Availability Layers Data availability (DA) refers to proving that data is readily accessible, verifiable, and retrievable. For example, Layer 2 rollups such as Arbitrum or Base reduce the burden on Ethereum by handling transactions off-chain and then publishing the data back to Ethereum, thereby freeing up L1 throughput and reducing gas costs. The transaction data, however, still needs to be made available so that anyone can validate or challenge the transactions through fraud proofs during the challenge period. As such, DA is crucial to blockchains as it allows for full validation of the blockchain's history and current state by any participant, thus maintaining the decentralized and trustless nature of the network. Without this, validators would not be able to independently verify the legitimacy of transactions and blocks, leading to potential issues like fraud or censorship. This led to the emergence of Data Availability Layers (DALs), which provide a significantly more efficient manner of storing and verifying data than publishing directly to Ethereum. DALs are critical for several reasons: - **Scalability**: DALs allow networks to process more transactions and larger datasets without overwhelming the system, reducing the burden on network nodes and significantly enhancing network scalability. - **Increased Efficiency**: DALs optimize how and where data is stored and made available, increasing data throughput and reducing latency while also minimizing associated costs. - **Interoperability & Innovation**: DALs that can interact with multiple ecosystems enable fast and highly secure interoperability for data and assets. However, it's worth noting that not all DALs are built equally. ## The Challenge Today Existing DALs tend to require that data be simultaneously sent to all of their network nodes, preventing horizontal scalability and limiting network speed to the slowest node. They also do not have built-in storage systems, requiring connectivity to external systems that impact throughput, latency, and cost. Additionally, 0G inherits Ethereum's security, while other systems rely upon their own security mechanisms that fall short. This is significant because Ethereum's network is secured by over 34 million ETH staked, representing approximately $80 billion in cryptoeconomic security at the time of writing. In contrast, competitors rely on security mechanisms that, at best, represent only a fraction of Ethereum's total security. This gives 0G a distinct advantage, as it leverages the vast economic incentives and decentralization of Ethereum's staking system, providing a level of protection that competitors cannot match. Even more issues exist, including EigenDA's lack of randomization over its data committees. As data committees are core to a DA system's integrity, a lack of randomization means that collusion is theoretically possible for malicious nodes to predict when they might be on a committee together. **0G's core differentiation is massive throughput and scalability.** This is possible through 0G's unique design includes a built-in storage system and horizontally scalable consensus design, alongside other clever design mechanisms that we'll cover below. The result is that 0G serves as the foundational layer for decentralized AI applications, bringing on-chain AI and more to life. ## Why 0G There are 4 differentiators of 0G worth highlighting: ### 1. Infinitely Scalable DA 0G's infinitely scalable DAL can quickly query or confirm data as valid, whether data is held by 0G Storage, or external Web2 or Web3 databases. Infinite scalability comes from the ability to continuously add new consensus networks, supporting workloads that far surpass the capacity of existing systems. ### 2. Modular and Layered Architecture 0G's design decouples storage, data availability, and consensus, allowing each component to be optimized for its specific function. Data availability is ensured through redundancy, with data distributed across decentralized Storage Nodes. Cryptographic proofs (like Merkle trees and zk-proofs) verify data integrity at regular intervals, automatically replacing nodes that fail to produce valid proofs. And combined with 0G's ability to keep adding new consensus networks that scale with demand, 0G can scale efficiently and is ideal for complex AI workflows and large-scale data processing. ### 3. Trust Layer for AI & High Throughput 0G is the trust layer for AI, designed to give users control over their data, while providing the infrastructure necessary to handle the massive throughput demands of AI applications. Beyond its modular architecture and infinite consensus layers, 0G achieves high throughput through parallel data processing, enabled by erasure coding, horizontally scalable consensus networks, and more. With a demonstrated throughput of 50 Gbps on the Galileo Testnet, 0G seamlessly supports AI workloads and other high-performance needs, including training large language models and managing AI agent networks. These differentiators make 0G uniquely positioned to tackle the challenges of scaling AI on a decentralized platform, which is critical for the future of Web3 and decentralized intelligence. ## How Does This Work? Data submitted to 0G DA is first erasure-coded and split into "data chunks," which are then distributed across various Storage Nodes in the 0G Storage network. To ensure data availability, 0G uses **Data Availability Nodes** that are randomly chosen using a Verifiable Random Function (VRF). A VRF generates random values in a way that is unpredictable yet verifiable by others, which is important as it prevents potentially malicious nodes from collusion. These DA nodes work together in small groups, called quorums, to check and verify the stored data. The system assumes that most nodes in each group will act honestly, known as an "honest majority" assumption. The consensus mechanism used by 0G is fast and efficient due to its sampling-based approach. Rather than verifying all data, DA nodes sample portions of it, drastically reducing the data they need to handle. Once enough nodes agree that the sampled data is available and correct, they submit availability proofs to the 0G Consensus network. This lightweight, sample-driven approach enables faster verification while maintaining strong security. Validators in the 0G Consensus network verify and finalize DA proofs Validators in the 0G Consensus network, who are separate from the DA nodes, verify and finalize these proofs. Although DA nodes ensure data availability, they do not directly participate in the final consensus process, which is the responsibility of 0G validators. Validators use a shared staking mechanism where they stake 0G tokens on a primary network (likely Ethereum). Any slashable event across connected networks leads to slashing on the main network, securing the system's scalability while maintaining robust security. This is a key mechanism that allows the system to scale infinitely while maintaining data availability. In return, validators engaged in shared staking receive 0G tokens on any network managed, which can then be burnt in return for 0G tokens on the mainnet. The lightweight, sample-driven consensus approach ## Use Cases 0G DA offers an infinitely scalable and high-performance DA solution for a wide range of applications across Web3, AI, and more. ### L1s / L2s Layer 1 and Layer 2 chains can utilize 0G DA to handle data availability and storage requirements for decentralized AI models, large datasets, and on-chain applications. Existing partners include networks like **Polygon, Optimism, Arbitrum, Fuel, Manta Network**, **and countless more**, which leverage 0G's scalable infrastructure to store data more efficiently and support fast retrieval. ### Decentralized Shared Sequencers Decentralized Shared Sequencers help order L2 transactions before final settlement on Ethereum. By integrating 0G DA, shared sequencers can streamline data across multiple networks in a decentralized manner, unlike existing sequencers which are often centralized. This also means fast and secure data transfers between L2s. ### Bridges Cross-chain bridges benefit from 0G DA's scalable storage and data availability features. Networks can store and retrieve state data using 0G DA, making state migration between networks faster and more secure. For example, a network can confirm a user's assets and transfer them securely to another chain using 0G's highly efficient data verification. ### Rollups-as-a-Service (RaaS) 0G DA can serve as a reliable DA solution for RaaS providers like **Caldera and AltLayer**, enabling seamless configuration and deployment of rollups. With 0G DA's highly scalable infrastructure, RaaS providers can ensure the secure availability of data across multiple rollups without compromising performance. ### DeFi 0G's DA infrastructure is ideally suited for DeFi applications that require fast settlement and high-frequency trading. For example, by storing order book data on 0G, DeFi projects can achieve faster transaction throughput and enhanced scalability across L2s and L3s. ### On-Chain Gaming On-chain gaming platforms rely on cryptographic proofs and metadata related to player assets, actions, and scores. 0G DA's ability to handle large volumes of data securely and efficiently makes it an optimal solution for gaming applications that require reliable data storage and fast retrieval. ### Data Markets Web3 data markets can benefit from 0G DA by storing datasets on-chain. The decentralized storage and retrieval capabilities of 0G enable real-time updates and querying of data, providing a reliable solution for data market platforms. ### AI & Machine Learning 0G DA is particularly focused on supporting decentralized AI, allowing full AI models and vast datasets to be stored and accessed on-chain. This infrastructure is essential for advanced AI applications that demand high data throughput and availability, such as training large language models (LLMs) and managing entire AI agent Networks. ## Getting Started Ready to integrate 0G DA into your project? - **Run a DA Node**: [Node operator guide](/run-a-node/da-node) - **Integration Guide**: [Developer documentation](/developer-hub/building-on-0g/da-integration) - **Technical Deep Dive**: [DA architecture details](/developer-hub/building-on-0g/da-deep-dive) --- *0G DA: Bringing infinite scalability to decentralized data availability.* --- ## DePIN Providers Source: https://docs.0g.ai/concepts/depin.md ## What is DePIN? DePIN (Decentralized Physical Infrastructure Networks) represents a revolutionary approach to building and scaling infrastructure networks. By combining physical hardware with blockchain incentives, DePIN networks create more open, decentralized, and cost-effective infrastructure across various sectors. :::success **Why DePIN Matters** Traditional infrastructure is expensive and centralized. DePIN democratizes access to computing power by utilizing underutilized hardware worldwide 🚀 ::: ## How 0G Leverages DePIN Infrastructure 0G Compute utilizes DePIN infrastructure to provide scalable, cost-effective computing resources for AI and blockchain applications. Rather than building massive centralized data centers, 0G partners with decentralized networks that aggregate distributed computing resources. ### Key Benefits of DePIN Integration **Cost Efficiency**: DePIN networks utilize existing underutilized hardware, reducing costs by up to 80% compared to traditional cloud providers. **Global Reach**: Distributed nodes worldwide provide low-latency access to computing resources regardless of geographic location. **Scalability**: New resources can be added to the network without physical infrastructure expansion, enabling rapid scaling. **Resilience**: No single point of failure with resources distributed across thousands of independent nodes. ## 0G's DePIN Partners ### [io.net](https://io.net) io.net operates the world's largest decentralized GPU network, specifically designed for machine learning and AI workloads. The network aggregates over 300,000 verified GPUs from independent data centers, crypto miners, and consumer hardware across 139 countries. **Key Capabilities:** - 6,000+ cluster-ready GPUs including NVIDIA H100s - 90% cost savings compared to traditional cloud providers - 90-second cluster deployment - Built on Ray.io framework (same as OpenAI's GPT training) ### [Aethir](https://aethir.com) Aethir provides enterprise-grade GPU-as-a-Service through its decentralized cloud infrastructure. Focused on AI, gaming, and virtualized computing, Aethir maintains over 43,000 enterprise-grade GPUs across 25 global locations. **Key Capabilities:** - 3,000+ NVIDIA H100s and H200s for advanced AI workloads - 99.99% uptime with enterprise-grade reliability - Ultra-low latency for real-time applications - Proof of Rendering verification system ## Technical Deep Dive
**What makes DePIN different from traditional cloud?** **Resource Utilization**: DePIN networks tap into idle hardware worldwide instead of building new data centers **Economic Model**: Token incentives create sustainable participation without massive capital expenditure **Geographic Distribution**: Resources are naturally distributed, reducing latency for global users **Permissionless Access**: Anyone can contribute resources or access compute power without gatekeepers
**How do DePIN networks ensure quality?** **Verification Systems**: Proof-of-Work, Proof-of-Capacity, and custom verification mechanisms **Quality Scoring**: Real-time monitoring and automated scoring of network participants **Economic Incentives**: Token rewards for good performance, slashing for poor performance **Redundancy**: Multiple nodes can handle the same task to ensure reliability
## The Future of Decentralized Computing The integration of 0G with DePIN infrastructure creates a comprehensive Web3 computing stack that addresses the growing demand for AI and blockchain applications. This partnership model enables: - **Affordable AI**: Making advanced AI computing accessible to startups and developers worldwide - **Scalable Infrastructure**: Meeting growing compute demands without massive capital investment - **Global Accessibility**: Bringing high-performance computing to underserved regions - **Sustainable Growth**: Utilizing existing hardware more efficiently ## Getting Started Ready to build with decentralized infrastructure? Explore these resources: - [0G Compute Network](/developer-hub/building-on-0g/compute-network/overview) - Learn about 0G's compute layer - [Build with Compute Router](/developer-hub/building-on-0g/compute-network/router/overview) - Recommended API gateway for building with 0G Compute - [Developer Hub](/developer-hub/getting-started) - Get started building on 0G --- _Powering the future of AI with decentralized infrastructure._ --- ## 0G Storage Source: https://docs.0g.ai/concepts/storage.md Current storage options force impossible tradeoffs: - **Cloud providers**: Fast but expensive with vendor lock-in - **Decentralized options**: Either slow (IPFS), limited (Filecoin), or prohibitively expensive (Arweave) ## What is 0G Storage? 0G Storage breaks these tradeoffs - a decentralized storage network that's as fast as AWS S3 but built for Web3. Purpose-designed for AI workloads and massive datasets.
New to decentralized storage? Traditional storage (like AWS): - One company controls your data - They can delete it, censor it, or change prices - Single point of failure Decentralized storage (like 0G): - Data spread across thousands of nodes - No single entity can delete or censor - Always available, even if nodes go offline
## Why Choose 0G Storage? ### 🚀 The Complete Package | What You Get | Why It Matters | |--------------|----------------| | **95% lower costs than AWS** | Sustainable for large datasets | | **Instant retrieval** | No waiting for critical data | | **Structured + unstructured data** | One solution for all storage needs | | **Universal compatibility** | Works with any blockchain or Web2 app | | **Proven scale** | Already handling TB-scale workloads | ## How It Works 0G Storage is a distributed data storage system designed with on-chain elements to incentivize storage nodes to store data on behalf of users. Anyone can run a storage node and receive rewards for maintaining one. ### Technical Architecture 0G Storage uses a two-lane system:
📤 Data Publishing Lane - Handles metadata and availability proofs - Verified through 0G Consensus network - Enables fast data discovery
💾 Data Storage Lane - Manages actual data storage - Every upload is committed on-chain as a Merkle root, so any node's copy can be verified against it - Durability comes from replication: many independent miners keep copies because PoRA pays them to - Automatic replication maintains availability
## Storage Layers for Different Needs ### 📁 Log Layer (Immutable Storage) **Perfect for**: AI training data, archives, backups - Append-only (write once, read many) - Optimized for large files - Lower cost for permanent storage **Use cases**: - ML datasets - Video/image archives - Blockchain history - General Large file storage ### 🔑 Key-Value Layer (Mutable Storage) **Perfect for**: Databases, dynamic content, state storage - Update existing data - Fast key-based retrieval - Real-time applications **Use cases**: - On-chain databases - User profiles - Game state - Collaborative documents ## How Storage Providers Earn 0G Storage is maintained by a network of miners incentivized to store and manage data through a unique consensus mechanism known as **Proof of Random Access (PoRA)**. ### How It Works 1. **Random Challenges**: System randomly asks miners to prove they have specific data 2. **Cryptographic Proof**: Miners must generate a valid hash (like Bitcoin mining) 3. **Quick Response**: Must respond fast to prove data is readily accessible 4. **Fair Rewards**: Successful proofs earn storage fees
What's PoRA in simple terms? Imagine a teacher randomly checking if students did their homework: 1. Teacher picks a random student (miner) 2. Asks for a specific page (data chunk) 3. Student must show it quickly 4. If correct, student gets rewarded This ensures miners actually store the data they claim to store.
### Fair Competition = Fair Reward To promote fairness, the mining range is capped at 8 TB of data per mining operation. **Why 8TB limit?** - Small miners can compete with large operations - Prevents centralization - Lower barrier to entry **For large operators**: Run multiple 8TB instances. **For individuals**: Focus on single 8TB range, still profitable ## How 0G Compares | Solution | Best For | Limitation | |----------|----------|------------| | **0G Storage** | AI/Web3 apps needing speed + scale | Newer ecosystem | | **AWS S3** | Traditional apps | Centralized, expensive | | **Filecoin** | Cold storage archival | Slow retrieval, unstructured only | | **Arweave** | Permanent storage | Extremely expensive | | **IPFS** | Small files, hobby projects | Very slow, no guarantees | ### 0G's Unique Position - Supports both structured and unstructured data - **Instant access** unlike other decentralized options - **Built for AI** from the ground up ## Frequently Asked Questions
Is my data really safe if nodes go offline? Yes. Your data is stored by many independent miners who are paid through PoRA to keep it, and every upload is committed on-chain as a Merkle root, so any copy can be verified. Individual node failures do not affect availability as long as other miners hold the data, which the incentives are designed to guarantee. Erasure coding is used by 0G DA, not by 0G Storage.
How fast can I retrieve large files? - Parallel retrieval from multiple nodes - Bandwidth limited only by your connection - 200 MBPS retrieval speed even at network congestion - CDN-like performance through geographic distribution
What happens to pricing as the network grows? The network fee is fixed. All pricing is transparent and on-chain, preventing hidden fees or sudden changes.
Can I migrate from existing storage? Yes, easily: 1. Keep existing infrastructure 2. Use 0G as overflow or backup 3. Gradually migrate based on access patterns
## Get Started ### 🧑‍💻 For Developers Integrate 0G Storage in minutes → [SDK Documentation](/developer-hub/building-on-0g/storage/sdk) ### ⛏️ For Storage Providers Earn by providing storage capacity → [Run a Storage Node](/run-a-node/storage-node) --- *0G Storage: Purpose-built for AI and Web3's massive data needs.* --- ## ERC-7857 Standard Source: https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc7857.md ## Overview ERC-7857 extends ERC-721 to support encrypted metadata, specifically designed for tokenizing AI agents and sensitive digital assets. :::info Prerequisites - Understanding of ERC-721 NFT standard - Basic cryptography knowledge (encryption, hashing) - Smart contract development experience - Familiarity with oracle systems ::: ### Document Purpose This page provides the technical specification, implementation details, and security considerations for ERC-7857. For high-level concepts, see the **[Agentic ID Overview](./overview)**. :::note Related Standard ERC-7857 governs the encrypted ownership and secure transfer of an agent's intelligence. For public, on-chain agent **discoverability** — the identity and reputation layer that 0G supports — see [ERC-8004 Trustless Agents](./erc8004). ::: ## Key Technical Features | Feature | Description | Benefit | |---------|-------------|--------| | **Encrypted Metadata** | Store sensitive data securely | Protects proprietary AI models | | **Secure Re-encryption** | Transfer without data exposure | Maintains privacy during ownership changes | | **Oracle Verification** | TEE/ZKP proof validation | Ensures transfer integrity | | **Authorized Usage** | Grant access without ownership | Enables AI-as-a-Service models | ## Technical Specification ### Core Interface ```solidity interface IERC7857 is IERC721 { // Transfer with metadata re-encryption function transfer( address from, address to, uint256 tokenId, bytes calldata sealedKey, bytes calldata proof ) external; // Clone token with same metadata function clone( address to, uint256 tokenId, bytes calldata sealedKey, bytes calldata proof ) external returns (uint256 newTokenId); // Authorize usage without revealing data function authorizeUsage( uint256 tokenId, address executor, bytes calldata permissions ) external; } ``` ### Transfer Architecture **Security Guarantees:** ✅ Metadata remains encrypted throughout process ✅ Only new owner can decrypt transferred data ✅ Transfer integrity cryptographically verified ✅ No intermediary can access sensitive information ## Oracle Implementations ERC-7857 supports two oracle types for secure metadata re-encryption: ### TEE (Trusted Execution Environment) **How it works:** 1. Sender transmits encrypted data + key to TEE 2. TEE securely decrypts data in isolated environment 3. TEE generates new key and re-encrypts metadata 4. TEE encrypts new key with receiver's public key 5. TEE outputs sealed key and hash values **Advantages:** - Hardware-level security guarantees - TEE can generate cryptographically secure keys - Attestation provides proof of secure execution #### TEE Implementation Example ```javascript class TEEOracle { async processTransfer(encryptedData, oldKey, receiverPublicKey) { // All operations happen inside secure enclave try { // Step 1: Decrypt original data const data = await this.decryptSecurely(encryptedData, oldKey); // Step 2: Generate new encryption key const newKey = await this.generateSecureKey(); // Step 3: Re-encrypt with new key const newEncryptedData = await this.encryptSecurely(data, newKey); // Step 4: Seal key for receiver const sealedKey = await this.sealForReceiver(newKey, receiverPublicKey); // Step 5: Generate attestation proof const proof = await this.generateAttestation({ originalHash: hash(encryptedData), newHash: hash(newEncryptedData), receiverKey: receiverPublicKey }); return { newEncryptedData, sealedKey, proof }; } catch (error) { throw new Error(`TEE processing failed: ${error.message}`); } } } ``` ### ZKP (Zero-Knowledge Proof) **How it works:** 1. Sender provides old and new keys to ZKP system 2. ZKP circuit verifies correct re-encryption 3. Proof generated without revealing keys or data 4. Smart contract validates ZKP proof **Considerations:** - Cannot independently generate new keys - Requires sender to handle key generation - Receivers should rotate keys post-transfer - Computationally intensive proof generation #### ZKP Circuit Example ```rust // ZKP circuit for verifying re-encryption use ark_relations::r1cs::SynthesisError; pub struct ReencryptionCircuit { // Public inputs (known to verifier) pub old_data_hash: Option, pub new_data_hash: Option, pub receiver_pubkey: Option, // Private inputs (known only to prover) pub encrypted_data: Option>, pub old_key: Option>, pub new_key: Option>, pub plaintext_data: Option>, } impl ConstraintSynthesizer for ReencryptionCircuit { fn generate_constraints( self, cs: ConstraintSystemRef, ) -> Result<(), SynthesisError> { // Step 1: Verify decryption of original data let decrypted = decrypt_constraint( cs.clone(), &self.encrypted_data?, &self.old_key? )?; // Step 2: Verify plaintext matches decrypted data enforce_equal( cs.clone(), &decrypted, &self.plaintext_data? )?; // Step 3: Verify re-encryption with new key let reencrypted = encrypt_constraint( cs.clone(), &self.plaintext_data?, &self.new_key? )?; // Step 4: Verify hash consistency let computed_hash = hash_constraint(cs.clone(), &reencrypted)?; enforce_equal( cs, &computed_hash, &self.new_data_hash? )?; Ok(()) } } ``` ## Implementation Guidelines ### Smart Contract Architecture ```solidity pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; contract ERC7857 is ERC721, Ownable, ReentrancyGuard { // State variables mapping(uint256 => bytes32) private _metadataHashes; mapping(uint256 => string) private _encryptedURIs; mapping(uint256 => mapping(address => bytes)) private _authorizations; // Oracle configuration address public oracle; uint256 public constant PROOF_VALIDITY_PERIOD = 1 hours; // Events event MetadataUpdated(uint256 indexed tokenId, bytes32 newHash); event UsageAuthorized(uint256 indexed tokenId, address indexed executor); event OracleUpdated(address oldOracle, address newOracle); modifier validProof(bytes calldata proof) { require(oracle != address(0), "Oracle not set"); require(IOracle(oracle).verifyProof(proof), "Invalid proof"); _; } function transfer( address from, address to, uint256 tokenId, bytes calldata sealedKey, bytes calldata proof ) external nonReentrant validProof(proof) { require(ownerOf(tokenId) == from, "Not owner"); require(to != address(0), "Invalid recipient"); // Update metadata access for new owner _updateMetadataAccess(tokenId, to, sealedKey, proof); // Transfer NFT ownership _transfer(from, to, tokenId); emit MetadataUpdated(tokenId, keccak256(sealedKey)); } function _updateMetadataAccess( uint256 tokenId, address newOwner, bytes calldata sealedKey, bytes calldata proof ) internal { // Verify proof contains correct metadata hash bytes32 expectedHash = _extractHashFromProof(proof); _metadataHashes[tokenId] = expectedHash; // Store new encrypted URI if provided string memory newURI = _extractURIFromProof(proof); if (bytes(newURI).length > 0) { _encryptedURIs[tokenId] = newURI; } } } ``` ### Metadata Management ```javascript class MetadataManager { constructor(storageProvider, encryptionService, options = {}) { this.storage = storageProvider; this.encryption = encryptionService; this.options = { keySize: 256, algorithm: 'AES-GCM', ...options }; } async storeMetadata(data, ownerPublicKey) { try { // Validate input data this._validateMetadata(data); // Generate encryption key const key = await this.encryption.generateKey({ size: this.options.keySize, algorithm: this.options.algorithm }); // Encrypt metadata const encrypted = await this.encryption.encrypt(data, key, { includeMac: true, version: '1.0' }); // Store encrypted data on distributed storage const uri = await this.storage.store(encrypted, { redundancy: 3, availability: '99.9%' }); // Seal key for owner using their public key const sealedKey = await this.encryption.sealForOwner( key, ownerPublicKey ); // Generate metadata hash for verification const metadataHash = await this.encryption.hash(encrypted); return { uri, sealedKey, metadataHash, algorithm: this.options.algorithm, version: '1.0' }; } catch (error) { throw new Error(`Metadata storage failed: ${error.message}`); } } async retrieveMetadata(uri, sealedKey, ownerPrivateKey) { try { // Fetch encrypted data from storage const encrypted = await this.storage.retrieve(uri); // Unseal the encryption key const key = await this.encryption.unsealKey( sealedKey, ownerPrivateKey ); // Decrypt and return metadata const decrypted = await this.encryption.decrypt(encrypted, key); return decrypted; } catch (error) { throw new Error(`Metadata retrieval failed: ${error.message}`); } } _validateMetadata(data) { if (!data || typeof data !== 'object') { throw new Error('Invalid metadata format'); } const maxSize = 10 * 1024 * 1024; // 10MB limit const serialized = JSON.stringify(data); if (serialized.length > maxSize) { throw new Error('Metadata exceeds size limit'); } } } ``` ## Security Considerations ### 🔑 Key Management **Best Practices:** - Use hardware security modules (HSM) when available - Implement automatic key rotation every 90 days - Store private keys in secure enclaves or hardware wallets - Never log or expose private keys in error messages **Implementation:** ```javascript class SecureKeyManager { constructor(hsmProvider) { this.hsm = hsmProvider; this.keyRotationInterval = 90 * 24 * 60 * 60 * 1000; // 90 days } async generateKey() { // Use HSM if available, fallback to secure random return this.hsm ? await this.hsm.generateKey() : await crypto.subtle.generateKey(/*...*/);; } } ``` ### 🔮 Oracle Security **TEE Verification:** - Always verify TEE attestations before accepting proofs - Validate enclave signatures and measurement values - Implement attestation freshness checks **ZKP Auditing:** - Audit circuit implementations thoroughly - Verify trusted setup parameters - Test edge cases and malformed inputs **Fallback Mechanisms:** ```solidity contract OracleManager { address[] public oracles; uint256 public minConfirmations = 2; function verifyWithFallback(bytes calldata proof) external view returns (bool) { uint256 confirmations = 0; for (uint i = 0; i < oracles.length; i++) { if (IOracle(oracles[i]).verifyProof(proof)) { confirmations++; } } return confirmations >= minConfirmations; } } ``` ### 🛡️ Metadata Privacy **Encryption Standards:** - Use AES-256-GCM for symmetric encryption - Implement RSA-4096 or ECC-P384 for key sealing - Always include authentication tags **Storage Security:** - Encrypt metadata before network transmission - Use 0G Storage for decentralized, tamper-proof storage - Implement zero-knowledge access controls **Access Patterns:** ```javascript // Secure metadata access pattern async function accessMetadata(tokenId, requesterKey) { // 1. Verify ownership or authorization const isAuthorized = await verifyAccess(tokenId, requesterKey); if (!isAuthorized) throw new Error('Unauthorized'); // 2. Retrieve encrypted metadata const encrypted = await storage.retrieve(getMetadataURI(tokenId)); // 3. Decrypt only if authorized const decrypted = await decrypt(encrypted, requesterKey); return decrypted; } ``` ## Advanced Features ### Clone Functionality The `clone()` function allows creating copies of Agentic IDs while maintaining metadata security: ```solidity function clone( address to, uint256 tokenId, bytes calldata sealedKey, bytes calldata proof ) external returns (uint256) { require(canClone(tokenId, msg.sender), "Not authorized"); uint256 newTokenId = _mint(to); _copyMetadata(tokenId, newTokenId, sealedKey, proof); return newTokenId; } ``` ### Authorized Usage Enable third parties to use Agentic ID capabilities without ownership: ```solidity function authorizeUsage( uint256 tokenId, address executor, bytes calldata permissions ) external { require(ownerOf(tokenId) == msg.sender, "Not owner"); _authorizations[tokenId][executor] = permissions; emit UsageAuthorized(tokenId, executor); } ``` ## 0G Infrastructure Integration ### 0G Storage Integration ```javascript // Store encrypted AI agent metadata const metadata = { model: aiAgent.serializedModel, weights: aiAgent.trainedWeights, config: aiAgent.configuration }; const encrypted = await encryptMetadata(metadata, ownerPublicKey); const storageResult = await ogStorage.store(encrypted, { redundancy: 3, durability: '99.999%' }); console.log(`Metadata stored at: ${storageResult.uri}`); ``` ### 0G Compute Integration ```javascript // Execute secure inference without exposing model const inferenceResult = await ogCompute.executeSecure({ tokenId: agenticTokenId, executor: authorizedExecutor, input: userQuery, verificationMode: 'TEE' // or 'ZKP' }); // Result includes proof of correct execution console.log(`Inference result: ${inferenceResult.output}`); console.log(`Verification proof: ${inferenceResult.proof}`); ``` ### 0G Chain Deployment ```javascript // Deploy Agentic ID contract to 0G Chain const ERC7857Factory = await ethers.getContractFactory('ERC7857'); const agenticIdContract = await ERC7857Factory.deploy( 'AI Agent NFTs', 'AINFT', oracleAddress, ogStorageAddress ); await agenticIdContract.deployed(); console.log(`Agentic ID contract deployed at: ${agenticIdContract.address}`); ``` ## Resources & References ### Official Documentation 📜 **[EIP-7857 Specification](https://github.com/ethereum/EIPs/pull/7857)** - Official Ethereum standard proposal 💻 **[Reference Implementation](https://github.com/0gfoundation/0g-agent-nft/tree/eip-7857-draft)** - Complete codebase with examples 🔒 **[Security Audit Reports](#)** - Third-party security assessments (coming soon) ### Community & Support 💬 **[Developer Forum](https://discord.gg/0glabs)** - Technical discussions and Q&A 🐛 **[GitHub Issues](https://github.com/0gfoundation/0g-agent-nft/issues)** - Bug reports and feature requests ### Standards & Specifications 📄 **[ERC-721 Standard](https://eips.ethereum.org/EIPS/eip-721)** - Base NFT standard 🔐 **[Encryption Standards](https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines)** - NIST cryptography guidelines 🛡️ **[TEE Specifications](https://software.intel.com/content/www/us/en/develop/topics/software-guard-extensions.html)** - Intel SGX documentation ## Next Steps ### For Implementation 🚀 **[Integration Guide](./integration)** - Step-by-step development guide 🎯 **[Use Cases](./overview#real-world-applications)** - Real-world implementation examples 📋 **[Best Practices Guide](#)** - Production deployment guidelines (coming soon) ### For Testing 🧪 **[Testnet Deployment](./integration#step-2-create-agentic-id-smart-contract)** - Test your implementation 🗗️ **[Oracle Testing](#)** - Verify TEE and ZKP implementations 🔍 **[Security Testing](#)** - Audit your contracts ### Community 💬 **Join Discussions** - Share implementations and get feedback 🚀 **Contribute** - Help improve the standard and tooling 📚 **Learn** - Explore advanced features and optimizations --- ## ERC-8004 Trustless Agents Source: https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/erc8004.md 0G officially supports **ERC-8004**, the Trustless Agent standard. 0G's ERC-8004 registry deployment is listed in the official [`erc-8004-contracts`](https://github.com/erc-8004/erc-8004-contracts) repository, so agents on 0G can be **discovered**, **verified**, and **interoperate** across the broader ERC-8004 agent ecosystem. :::tip Navigation Guide - **This page**: 0G's ERC-8004 support, registry addresses, and agent discovery - **[Agentic ID Overview](./overview)**: High-level Agentic ID concepts - **[ERC-7857 Standard](./erc7857)**: The encrypted-ownership standard behind Agentic IDs - **[Integration Guide](./integration)**: Step-by-step development guide ::: ## What Is ERC-8004? **ERC-8004 ("Trustless Agents")** is an Ethereum standard that defines a lightweight set of on-chain registries so autonomous AI agents can be **discovered, identified, and trusted across organizational boundaries** — without any pre-existing trust or a centralized intermediary. It gives every agent a portable, verifiable identity that any ecosystem tool can read, complementing agent-to-agent protocols (such as A2A and MCP) with an on-chain trust layer. ### The Registries | Registry | Role | |----------|------| | **Identity Registry** | Assigns each agent a global `agentId` and points to its off-chain *agent card* (name, description, endpoints, capabilities). This is the core discoverability record. | | **Reputation Registry** | Stores signed feedback so agents can accumulate portable, verifiable reputation. | | **Validation Registry** | Optional, independent verification of agent behavior. Defined by the standard and still evolving. | ## 0G Support for ERC-8004 0G has deployed the ERC-8004 reference registries on 0G Chain, and 0G's deployment is listed in the canonical [`erc-8004-contracts`](https://github.com/erc-8004/erc-8004-contracts) repository. This gives 0G agents three things: - **Discoverability** — an agent registered on 0G is visible to any ERC-8004-aware tool or indexer. - **Interoperability** — 0G agents share the same identity and reputation graph as agents on other ERC-8004 chains. - **Standard alignment** — 0G agents follow the same registration and agent-card model as the rest of the ecosystem. ### 0G Registry Addresses The `agentId` space is a **global, shared counter** on the Identity Registry — it is not scoped per project or per app. **0G Mainnet** (chain ID `16661`) | Registry | Address | |----------|---------| | **Identity Registry** | [`0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`](https://chainscan.0g.ai/address/0x8004A169FB4a3325136EB29fA0ceB6D2e539a432) | | **Reputation Registry** | [`0x8004BAa17C55a88189AE136b182e5fdA19dE9b63`](https://chainscan.0g.ai/address/0x8004BAa17C55a88189AE136b182e5fdA19dE9b63) | **0G Galileo Testnet** (chain ID `16602`) | Registry | Address | |----------|---------| | **Identity Registry** | [`0x8004A818BFB912233c491871b3d84c89A494BD9e`](https://chainscan-galileo.0g.ai/address/0x8004A818BFB912233c491871b3d84c89A494BD9e) | | **Reputation Registry** | [`0x8004B663056A597Dffe9eCcC1965A193B7388713`](https://chainscan-galileo.0g.ai/address/0x8004B663056A597Dffe9eCcC1965A193B7388713) | ## Discover Agents on 8004scan [8004scan.io](https://8004scan.io) is an explorer for ERC-8004 agents. Once an agent is registered, it appears there — its `agentId`, chain, service endpoints, and reputation — alongside agents from across the ecosystem. ## Agentic ID and ERC-8004 [Agentic ID](/concepts/agentic-id) is 0G's agent-identity surface, and it is **ERC-8004 compatible**: an Agentic ID can carry a corresponding ERC-8004 registration, so an agent created on 0G is discoverable through the standard while its ownership and encrypted intelligence continue to be governed by [ERC-7857](./erc7857). ## Resources - **ERC-8004 standard** — [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) - **Reference contracts** — [`erc-8004/erc-8004-contracts`](https://github.com/erc-8004/erc-8004-contracts) - **Agent explorer** — [8004scan.io](https://8004scan.io) - **Related standard on 0G** — [ERC-7857](./erc7857) · [Agentic ID Overview](./overview) --- ## Agentic ID Integration Guide Source: https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/integration.md ## Overview This step-by-step guide shows you how to integrate Agentic IDs into your applications using the 0G ecosystem. You'll learn to deploy contracts, manage metadata, and implement secure transfers. :::tip Quick Navigation - **New to Agentic IDs?** Start with [Agentic ID Overview](./overview) - **Need technical details?** See [ERC-7857 Standard](./erc7857) - **Interested in agent discoverability?** See [ERC-8004 Trustless Agents](./erc8004) - **Ready to build?** Continue with this guide ::: ## Prerequisites ### Knowledge Requirements ✅ **NFT Standards** - Understanding of ERC-721 basics ✅ **Smart Contracts** - Solidity development experience ✅ **Cryptography** - Basic encryption and key management concepts ✅ **0G Ecosystem** - Familiarity with 0G infrastructure components ### Technical Setup ✅ **Development Environment** - Node.js 16+, Hardhat/Foundry ✅ **0G Testnet Account** - Wallet with testnet tokens ✅ **API Access** - Keys for 0G Storage and Compute services
Quick Setup Checklist ```bash # Install dependencies npm install @0gfoundation/0g-storage-ts-sdk ethers hardhat # Set environment variables export PRIVATE_KEY="your-private-key" export OG_RPC_URL="https://evmrpc-testnet.0g.ai" export OG_STORAGE_URL="https://storage-testnet.0g.ai" export OG_COMPUTE_URL="https://compute-testnet.0g.ai" ```
## Understanding 0G Integration Agentic IDs work seamlessly with 0G's complete AI infrastructure: | Component | Purpose | Agentic ID Integration | |-----------|---------|------------------| | **0G Storage** | Encrypted metadata storage | Stores AI agent data securely | | **0G DA** | Proof verification | Validates transfer integrity | | **0G Chain** | Smart contract execution | Hosts Agentic ID contracts | | **0G Compute** | Secure AI inference | Runs agent computations privately | :::note Why This Architecture Matters This integration ensures that AI agents maintain their intelligence, privacy, and functionality throughout their entire lifecycle while remaining fully decentralized. ::: ## Step-by-Step Implementation ### Step 1: Initialize Your Project ```bash # Create new project mkdir my-agentic-id-project && cd my-agentic-id-project npm init -y # Install required dependencies npm install @0gfoundation/0g-storage-ts-sdk @openzeppelin/contracts ethers hardhat npm install --save-dev @nomicfoundation/hardhat-toolbox # Initialize Hardhat npx hardhat init ``` **Configure environment:** ```bash # Create .env file cat > .env << EOF PRIVATE_KEY=your_private_key_here OG_RPC_URL=https://evmrpc-testnet.0g.ai OG_STORAGE_URL=https://storage-testnet.0g.ai OG_COMPUTE_URL=https://compute-testnet.0g.ai EOF ``` ### Step 2: Create Agentic ID Smart Contract ```solidity // contracts/AgenticID.sol pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; interface IOracle { function verifyProof(bytes calldata proof) external view returns (bool); } contract AgenticID is ERC721, Ownable, ReentrancyGuard { // State variables mapping(uint256 => bytes32) private _metadataHashes; mapping(uint256 => string) private _encryptedURIs; mapping(uint256 => mapping(address => bytes)) private _authorizations; address public oracle; uint256 private _nextTokenId = 1; // Events event MetadataUpdated(uint256 indexed tokenId, bytes32 newHash); event UsageAuthorized(uint256 indexed tokenId, address indexed executor); constructor( string memory name, string memory symbol, address _oracle ) ERC721(name, symbol) { oracle = _oracle; } function mint( address to, string calldata encryptedURI, bytes32 metadataHash ) external onlyOwner returns (uint256) { uint256 tokenId = _nextTokenId++; _safeMint(to, tokenId); _encryptedURIs[tokenId] = encryptedURI; _metadataHashes[tokenId] = metadataHash; return tokenId; } function transfer( address from, address to, uint256 tokenId, bytes calldata sealedKey, bytes calldata proof ) external nonReentrant { require(ownerOf(tokenId) == from, "Not owner"); require(IOracle(oracle).verifyProof(proof), "Invalid proof"); // Update metadata access for new owner _updateMetadataAccess(tokenId, to, sealedKey, proof); // Transfer token ownership _transfer(from, to, tokenId); emit MetadataUpdated(tokenId, keccak256(sealedKey)); } function authorizeUsage( uint256 tokenId, address executor, bytes calldata permissions ) external { require(ownerOf(tokenId) == msg.sender, "Not owner"); _authorizations[tokenId][executor] = permissions; emit UsageAuthorized(tokenId, executor); } function _updateMetadataAccess( uint256 tokenId, address newOwner, bytes calldata sealedKey, bytes calldata proof ) internal { // Extract new metadata hash from proof bytes32 newHash = bytes32(proof[0:32]); _metadataHashes[tokenId] = newHash; // Update encrypted URI if provided in proof if (proof.length > 64) { string memory newURI = string(proof[64:]); _encryptedURIs[tokenId] = newURI; } } function getMetadataHash(uint256 tokenId) external view returns (bytes32) { return _metadataHashes[tokenId]; } function getEncryptedURI(uint256 tokenId) external view returns (string memory) { return _encryptedURIs[tokenId]; } } ``` ### Step 3: Deploy and Initialize Contract **Create deployment script:** ```javascript // scripts/deploy.js const { ethers } = require("hardhat"); async function main() { const [deployer] = await ethers.getSigners(); console.log("Deploying contracts with account:", deployer.address); // Deploy mock oracle for testing (replace with real oracle in production) const MockOracle = await ethers.getContractFactory("MockOracle"); const oracle = await MockOracle.deploy(); await oracle.deployed(); // Deploy Agentic ID contract const AgenticID = await ethers.getContractFactory("AgenticID"); const agenticId = await AgenticID.deploy( "AI Agent NFTs", "AINFT", oracle.address ); await agenticId.deployed(); console.log("Oracle deployed to:", oracle.address); console.log("Agentic ID deployed to:", agenticId.address); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ``` **Deploy to 0G testnet:** ```bash npx hardhat run scripts/deploy.js --network og-testnet ``` ### Step 4: Implement Metadata Management **Create metadata manager:** ```javascript // lib/MetadataManager.js const { ethers } = require('ethers'); const crypto = require('crypto'); class MetadataManager { constructor(ogStorage, encryptionService) { this.storage = ogStorage; this.encryption = encryptionService; } async createAIAgent(aiModelData, ownerPublicKey) { try { // Prepare AI agent metadata const metadata = { model: aiModelData.model, weights: aiModelData.weights, config: aiModelData.config, capabilities: aiModelData.capabilities, version: '1.0', createdAt: Date.now() }; // Generate encryption key const encryptionKey = crypto.randomBytes(32); // Encrypt metadata const encryptedData = await this.encryption.encrypt( JSON.stringify(metadata), encryptionKey ); // Store on 0G Storage const storageResult = await this.storage.store(encryptedData); // Seal key for owner const sealedKey = await this.encryption.sealKey( encryptionKey, ownerPublicKey ); // Generate metadata hash const metadataHash = ethers.utils.keccak256( ethers.utils.toUtf8Bytes(JSON.stringify(metadata)) ); return { encryptedURI: storageResult.uri, sealedKey, metadataHash }; } catch (error) { throw new Error(`Failed to create AI agent: ${error.message}`); } } async mintAgenticID(contract, recipient, aiAgentData) { const { encryptedURI, sealedKey, metadataHash } = aiAgentData; const tx = await contract.mint( recipient, encryptedURI, metadataHash ); const receipt = await tx.wait(); const tokenId = receipt.events[0].args.tokenId; return { tokenId, sealedKey, transactionHash: receipt.transactionHash }; } } module.exports = MetadataManager; ``` ### Step 5: Implement Secure Transfers **Transfer preparation:** ```javascript // lib/TransferManager.js class TransferManager { constructor(oracle, metadataManager) { this.oracle = oracle; this.metadata = metadataManager; } async prepareTransfer(tokenId, fromAddress, toAddress, toPublicKey) { try { // Retrieve current metadata const currentURI = await this.metadata.getEncryptedURI(tokenId); const encryptedData = await this.storage.retrieve(currentURI); // Request oracle to re-encrypt for new owner const transferRequest = { tokenId, encryptedData, fromAddress, toAddress, toPublicKey }; // Get oracle proof and new sealed key const oracleResponse = await this.oracle.processTransfer(transferRequest); return { sealedKey: oracleResponse.sealedKey, proof: oracleResponse.proof, newEncryptedURI: oracleResponse.newURI }; } catch (error) { throw new Error(`Transfer preparation failed: ${error.message}`); } } async executeTransfer(contract, transferData) { const { from, to, tokenId, sealedKey, proof } = transferData; const tx = await contract.transfer( from, to, tokenId, sealedKey, proof ); return await tx.wait(); } } ``` ## Best Practices ### 🔒 Security Guidelines **Key Management:** - Store private keys in hardware wallets or HSMs - Never expose keys in code or logs - Implement automatic key rotation - Use multi-signature wallets for critical operations **Metadata Protection:** ```javascript // Example: Secure metadata handling class SecureMetadata { constructor() { this.encryptionAlgorithm = 'aes-256-gcm'; this.keyDerivation = 'pbkdf2'; } async encryptMetadata(data, password) { const salt = crypto.randomBytes(16); const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha512'); const iv = crypto.randomBytes(16); const cipher = crypto.createCipher(this.encryptionAlgorithm, key, iv); // ... encryption logic } } ``` ### ⚡ Performance Optimization **Efficient Storage Patterns:** - Compress metadata before encryption - Use appropriate storage tiers based on access patterns - Implement lazy loading for large AI models - Cache frequently accessed data locally **Batch Operations:** ```javascript // Batch multiple operations async function batchMintAgenticIDs(agents, recipients) { const operations = agents.map((agent, i) => metadataManager.createAIAgent(agent, recipients[i]) ); const results = await Promise.all(operations); return results; } ``` ### 🧪 Testing Strategy **Comprehensive Test Suite:** ```javascript // test/Agentic ID.test.js describe('Agentic ID Contract', function () { it('should mint Agentic ID with encrypted metadata', async function () { const metadata = await createTestMetadata(); const result = await agenticId.mint(owner.address, metadata.uri, metadata.hash); expect(result).to.emit(agenticId, 'Transfer'); }); it('should transfer with re-encryption', async function () { // Test secure transfer logic }); it('should authorize usage without ownership transfer', async function () { // Test authorization functionality }); }); ``` **Security Testing:** - Test with malformed proofs - Verify access controls - Check for reentrancy vulnerabilities - Validate oracle responses ## Real-World Use Cases ### 🏪 AI Agent Marketplace **Complete marketplace integration:** ```javascript // marketplace/AgentMarketplace.js class AgentMarketplace { constructor(agenticIdContract, paymentToken) { this.agenticId = agenticIdContract; this.payment = paymentToken; this.listings = new Map(); } async listAgent(tokenId, price, description) { // Verify ownership const owner = await this.agenticId.ownerOf(tokenId); require(owner === msg.sender, 'Not owner'); // Create listing const listing = { tokenId, price, description, seller: owner, isActive: true }; this.listings.set(tokenId, listing); // Approve marketplace for transfer await this.agenticId.approve(this.address, tokenId); return listing; } async purchaseAgent(tokenId, buyerPublicKey) { const listing = this.listings.get(tokenId); require(listing && listing.isActive, 'Agent not for sale'); // Prepare secure transfer const transferData = await this.prepareTransfer( tokenId, listing.seller, msg.sender, buyerPublicKey ); // Execute payment await this.payment.transferFrom(msg.sender, listing.seller, listing.price); // Execute secure transfer await this.agenticId.transfer( listing.seller, msg.sender, tokenId, transferData.sealedKey, transferData.proof ); // Remove listing this.listings.delete(tokenId); } } ``` ### 💼 AI-as-a-Service Platform **Usage authorization system:** ```javascript // services/AIaaS.js class AIaaSPlatform { async createSubscription(tokenId, subscriber, duration, permissions) { // Verify agent ownership const owner = await this.agenticId.ownerOf(tokenId); // Create usage authorization const authData = { subscriber, expiresAt: Date.now() + duration, permissions: { maxRequests: permissions.maxRequests, allowedOperations: permissions.operations, rateLimit: permissions.rateLimit } }; // Grant usage rights await this.agenticId.authorizeUsage( tokenId, subscriber, ethers.utils.toUtf8Bytes(JSON.stringify(authData)) ); return authData; } async executeAuthorizedInference(tokenId, input, subscriber) { // Verify authorization const auth = await this.getAuthorization(tokenId, subscriber); require(auth && auth.expiresAt > Date.now(), 'Unauthorized'); // Execute inference on 0G Compute const result = await this.ogCompute.executeSecure({ tokenId, executor: subscriber, input, verificationMode: 'TEE' }); // Update usage metrics await this.updateUsageMetrics(tokenId, subscriber); return result; } } ``` ### 🤝 Multi-Agent Collaboration **Agent composition framework:** ```javascript // collaboration/AgentComposer.js class AgentComposer { async composeAgents(agentTokenIds, compositionRules) { // Verify ownership of all agents for (const tokenId of agentTokenIds) { const owner = await this.agenticId.ownerOf(tokenId); require(owner === msg.sender, `Not owner of agent ${tokenId}`); } // Create composite agent metadata const compositeMetadata = { type: 'composite', agents: agentTokenIds, rules: compositionRules, createdAt: Date.now() }; // Encrypt and store composite metadata const encryptedComposite = await this.metadataManager.createAIAgent( compositeMetadata, msg.sender ); // Mint new Agentic ID for composite agent const result = await this.agenticId.mint( msg.sender, encryptedComposite.encryptedURI, encryptedComposite.metadataHash ); return result.tokenId; } async executeCompositeInference(compositeTokenId, input) { // Retrieve composite metadata const metadata = await this.getDecryptedMetadata(compositeTokenId); // Execute inference on each component agent const agentResults = await Promise.all( metadata.agents.map(agentId => this.executeAgentInference(agentId, input) ) ); // Apply composition rules to combine results const finalResult = this.applyCompositionRules( agentResults, metadata.rules ); return finalResult; } } ``` ## Troubleshooting ### Common Issues & Solutions
Transfer Failures **Problem**: Agentic ID transfer transaction reverts **Causes & Solutions**: - **Invalid proof**: Verify oracle is online and proof is correctly formatted - **Expired proof**: Generate new proof (proofs have limited validity) - **Wrong owner**: Ensure `from` address matches actual token owner - **Oracle unavailable**: Check oracle service status ```javascript // Debug transfer issues async function debugTransfer(tokenId, proof) { const owner = await agenticId.ownerOf(tokenId); console.log(`Token owner: ${owner}`); const isValidProof = await oracle.verifyProof(proof); console.log(`Proof valid: ${isValidProof}`); // Check oracle status const oracleStatus = await oracle.getStatus(); console.log(`Oracle status: ${oracleStatus}`); } ```
Metadata Access Issues **Problem**: Cannot decrypt or access AI agent metadata **Solutions**: - Verify private key corresponds to sealed key - Check storage URI accessibility - Ensure metadata hasn't been corrupted - Validate encryption algorithm compatibility ```javascript // Test metadata access async function testMetadataAccess(tokenId, privateKey) { try { const encryptedURI = await agenticId.getEncryptedURI(tokenId); const encryptedData = await storage.retrieve(encryptedURI); // Attempt decryption const sealedKey = await getSealedKey(tokenId); const key = await unsealKey(sealedKey, privateKey); const metadata = await decrypt(encryptedData, key); console.log('Metadata accessible:', !!metadata); return metadata; } catch (error) { console.error('Metadata access failed:', error.message); } } ```
High Gas Costs **Optimization strategies**: - Compress proofs before submission - Use batch operations for multiple transfers - Optimize storage patterns - Consider Layer 2 solutions ```javascript // Optimize gas usage async function optimizedTransfer(transfers) { // Batch multiple transfers const batchData = transfers.map(t => ({ tokenId: t.tokenId, from: t.from, to: t.to, sealedKey: compressData(t.sealedKey), proof: compressProof(t.proof) })); return await agenticId.batchTransfer(batchData); } ```
### Get Support 🐛 **[GitHub Issues](https://github.com/0gfoundation/0g-agent-nft/issues)** - Report bugs and feature requests 💬 **[Discord Community](https://discord.gg/0glabs)** - Get help from developers 📖 **[Documentation](./erc7857)** - Technical reference ## Next Steps ### Continue Learning 📋 **[ERC-7857 Technical Standard](./erc7857)** - Deep dive into implementation details 🎯 **[Agentic ID Use Cases](./overview#real-world-applications)** - Explore more applications 💻 **[Example Implementations](https://github.com/0gfoundation/0g-agent-nft/tree/eip-7857-draft)** - Reference code ### Production Deployment 🚀 **Mainnet Migration** - Deploy to 0G mainnet when ready 🔒 **Security Audit** - Get your contracts audited 📊 **Monitoring Setup** - Implement monitoring and alerts ### Community 🤝 **Developer Community** - Share your implementation 💬 **Technical Discussions** - Join conversations about best practices 👥 **Contribute** - Help improve the Agentic ID ecosystem :::tip Ready to Deploy? Once you've tested your implementation thoroughly, consider getting a security audit before deploying to mainnet. The 0G team can recommend trusted auditing partners. ::: --- ## Agentic ID Overview Source: https://docs.0g.ai/developer-hub/building-on-0g/agentic-id/overview.md ## What Are Agentic IDs? The rapid growth of AI agents necessitates new methods for managing their ownership, transfer, and capabilities within Web3 ecosystems. **Agentic IDs** (formerly Intelligent NFTs) represent a significant advancement in this space, enabling the tokenization of AI agents with: - **Transferability**: Move AI agents between owners securely - **Decentralized control**: No single point of failure - **Full asset ownership**: Complete control over AI capabilities - **Royalty potential**: Monetize AI agent usage and transfers :::tip Navigation Guide - **This page**: High-level concepts and use cases - **[ERC-7857 Standard](./erc7857)**: Technical implementation details - **[Integration Guide](./integration)**: Step-by-step development guide - **[ERC-8004 Trustless Agents](./erc8004)**: Discoverability across the agent ecosystem ::: ## Why Traditional NFTs Don't Work for AI Traditional NFT standards like ERC-721 and ERC-1155 have significant limitations when applied to AI agents: ### Key Problems **🔓 Static and Public Metadata** - Existing standards link to static, publicly accessible metadata - AI agents need dynamic metadata that reflects learning and evolution - Sensitive AI data requires privacy protection **🚫 Insecure Metadata Transfer** - ERC-721 transfers only move ownership identifiers - The underlying AI "intelligence" doesn't transfer - New owners receive incomplete or non-functional agents **🔒 No Native Encryption** - Current standards lack built-in encryption support - Proprietary AI models remain exposed - Sensitive user data can't be protected ## The Agentic ID Solution: ERC-7857 ERC-7857 is a new NFT standard specifically designed to address AI agent requirements. It enables the creation, ownership, and secure transfer of Agentic IDs with their complete intelligence intact. ### Revolutionary Features **🛡️ Privacy-Preserving Metadata** - Encrypts sensitive AI "intelligence" data - Protects proprietary information from exposure - Maintains privacy throughout transfers **🔄 Secure Metadata Transfers** - Both ownership AND encrypted metadata transfer together - Verifiable transfer process ensures integrity - New owners receive fully functional agents **⚡ Dynamic Data Management** - Supports evolving AI agent capabilities - Secure updates to agent state and behaviors - Maintains functionality within NFT framework **🌐 Decentralized Storage Integration** - Works with 0G Storage for permanent, tamper-proof storage - Distributed access management - No single point of failure **✅ Verifiable Ownership & Control** - Cryptographic proofs validate all transfers - Oracle-based verification ensures integrity - Transparent ownership verification **🤖 AI-Specific Functionality** - Built-in agent lifecycle management - Pre-execution ownership verification - Specialized features for AI use cases ## How Agentic ID Transfers Work The transfer mechanism ensures both token ownership and encrypted metadata transfer securely together. ### Simple Transfer Flow ```text 1. 📦 Encrypt & Commit → 2. 🔄 Oracle Processing ↓ ↓ 6. ✅ Access Granted ← 3. 🔐 Re-encrypt for Receiver ↑ ↓ 5. ✓ Verify & Finalize ← 4. 🗝️ Secure Key Delivery ```
Detailed Step-by-Step Process 1. **Encryption & Commitment** - AI agent metadata gets encrypted - Hash commitment created as authenticity proof - Content remains hidden 2. **Secure Transfer Initiation** - Trusted oracle (using TEEs) decrypts original metadata - Process happens in secure environment 3. **Re-encryption for Receiver** - Oracle generates new encryption key - Re-encrypts metadata with new key - Stores new encrypted metadata (e.g., on 0G Storage) 4. **Key Delivery** - New encryption key encrypted with receiver's public key - Only intended owner can access metadata key 5. **Verification & Finalization** - Smart contract verifies multiple proofs: - Sender's access rights - Oracle validation of metadata matching - Receiver's signed acknowledgment - If valid: ownership transfers + receiver gets encrypted key 6. **Access Granted** - Receiver uses private key to decrypt metadata key - Full access to agent's encrypted intelligence granted
:::note Technical Implementation For detailed oracle implementations (TEE vs ZKP), security considerations, and code examples, see the **[ERC-7857 Technical Standard](./erc7857)**. ::: ### Additional Capabilities **🧬 Clone Function** - Creates new token with same AI metadata - Preserves original while enabling distribution - Useful for AI agent templates **🔐 Authorized Usage** - Grant usage rights without ownership transfer - Sealed executor processes metadata securely - Enable AI-as-a-Service models ## ERC-8004 Compatibility 0G officially supports **ERC-8004**, the Trustless Agent standard for on-chain agent identity, discoverability, and reputation. Agentic IDs are ERC-8004 compatible: an Agentic ID can carry a corresponding ERC-8004 registration, so agents created on 0G are discoverable and interoperable across the broader ERC-8004 ecosystem and listed on [8004scan](https://8004scan.io). See the **[ERC-8004 Trustless Agents](./erc8004)** guide for registry addresses and details. ## Real-World Applications Secure AI agent tokenization opens up transformative possibilities: ### 🏪 AI Agent Marketplaces - Buy and sell trained AI agents with guaranteed capability transfer - Secure marketplaces with verified agent functionality - Transparent pricing and capability verification ### 🎯 Personalized Automation - Own AI agents tailored for specific tasks: - DeFi trading strategies - Airdrop claiming automation - Social media management - Research and analysis ### 🏢 Enterprise AI Solutions - Build proprietary AI agents for internal use - Securely transfer or lease agents to clients - Maintain control over sensitive business logic ### 💼 AI-as-a-Service (AIaaS) - Tokenize AI agents for subscription models - Granular usage permissions and billing - Scalable service delivery ### 🤝 Agent Collaboration - Combine multiple Agentic ID agents for enhanced capabilities - Create composite AI solutions - Build AI agent ecosystems ### 💰 IP Monetization - AI developers monetize models as NFTs - Maintain usage control and royalty collection - Protect proprietary algorithms ## Powered by 0G Infrastructure Agentic IDs leverage the complete 0G ecosystem for optimal performance: | Component | Role in Agentic IDs | Key Benefits | |-----------|---------------|-------------| | **0G Storage** | Encrypted metadata storage | Secure, permanent, owner-only access | | **0G DA** | Transfer proof verification | Guaranteed metadata availability | | **0G Chain** | Smart contract execution | Fast, low-cost Agentic ID operations | | **0G Compute** | Secure AI inference | Private agent execution | ### Why This Matters By combining Agentic IDs with 0G's comprehensive AI infrastructure, developers can create sophisticated, transferable AI agents that maintain their intelligence, privacy, and functionality throughout their entire lifecycle. :::info Complete AI Stack 0G provides the only complete infrastructure stack specifically designed for AI applications, making it the ideal foundation for Agentic ID development. ::: ## Next Steps ### For Developers 🚀 **[Integration Guide](./integration)** - Start building with Agentic IDs 📋 **[ERC-7857 Standard](./erc7857)** - Technical implementation details 🌐 **[ERC-8004 Trustless Agents](./erc8004)** - Make your agents discoverable 💻 **[GitHub Repository](https://github.com/0gfoundation/0g-agent-nft/tree/eip-7857-draft)** - Sample code and examples ### For Users 🛒 **[AI Agent Marketplace](#)** - Browse available AI agents (coming soon) 📚 **[User Guide](#)** - How to buy, transfer, and use Agentic IDs (coming soon) ### Get Support 💬 **[Discord Community](https://discord.gg/0glabs)** - Ask questions and get help 📖 **[Documentation Hub](/)** - Complete 0G ecosystem guides :::tip Web3 Compatible ERC-7857 is designed to be compatible with existing Web3 infrastructure while providing enhanced security and functionality for AI agent tokenization. ::: --- ## Babylon AVS on 0G DA Source: https://docs.0g.ai/developer-hub/building-on-0g/avs/babylon-avs-on-0g-da.md Under construction... --- ## EigenLayer AVS on 0G DA Source: https://docs.0g.ai/developer-hub/building-on-0g/avs/eigenlayer-avs-on-0g-da.md Under construction... --- ## Account Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/account-management.md Both **[Direct Inference](./inference)** and **[Fine-tuning](./fine-tuning)** use the same per-provider account system: you deposit to a main account, transfer funds to each provider's sub-account, and the provider deducts from there as you use the service. This page is the shared reference for all operations — Web UI, CLI, and SDK. :::note Using the Router instead? The [Router](./router/overview) has its own unified billing and does **not** use per-provider sub-accounts. Router deposits, balance, API keys, and usage live elsewhere — see [Router → Deposits & Billing](./router/account/deposits) and [Router → Authentication](./router/authentication). ::: ## Overview The account system provides a secure and flexible way to manage funds across different AI service providers. ### Account Structure - **Main Account**: Your primary wallet where funds are deposited. All deposits go here first, and you can withdraw funds from here back to your wallet. - **Sub-Accounts**: Provider-specific accounts created automatically when you transfer funds to a provider. Each provider has a separate sub-account where funds are locked for their specific services. ### Fund Flow 1. **Deposit**: Transfer funds from your wallet to your Main Account 2. **Transfer**: Move funds from Main Account to Provider Sub-Accounts 3. **Usage**: Provider deducts from Sub-Account for services rendered 4. **Refund Request**: Initiate refund from Sub-Account (enters 24-hour lock period) 5. **Complete Refund**: After lock period expires, call retrieve-fund again to complete transfer back to Main Account 6. **Withdraw**: Transfer funds from Main Account back to your wallet ### Security Features - **24-hour lock period** for refunds to protect providers from abuse - **Single-use authentication** for each request to prevent replay attacks - **On-chain verification** for all transactions ensuring transparency - **Provider acknowledgment** required before first use of services ## Prerequisites - Node.js >= 20.0.0 - A wallet with 0G tokens (for testnet or mainnet) - EVM compatible wallet (for Web UI) ## Choose Your Interface | Feature | Web UI | CLI | SDK | |---------|--------|-----|-----| | Setup time | ~1 min | ~2 min | ~5 min | | Visual dashboard | ✅ | ❌ | ❌ | | Automation | ❌ | ✅ | ✅ | | App integration | ❌ | ❌ | ✅ | **Best for:** Quick account management with visual dashboard ### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk -g ``` ### Launch Web UI ```bash 0g-compute-cli ui start-web ``` Access the Web UI at `http://localhost:3090/wallet` where you can: - View your account balance in real-time - Deposit funds directly from your connected wallet - Transfer funds to provider sub-accounts - Monitor spending and usage - Request refunds with a visual interface **Best for:** Automation, scripting, and server environments ### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk -g ``` ### Setup Environment #### Choose Network ```bash 0g-compute-cli setup-network ``` #### Login with Wallet Enter your wallet private key when prompted. This will be used for account management and service payments. ```bash 0g-compute-cli login ``` ### CLI Commands #### Deposit Funds Add funds to your main account: ```bash 0g-compute-cli deposit --amount 10 ``` #### Check Balance View your account overview: ```bash 0g-compute-cli get-account ``` Example output: ```text Overview ┌──────────────────────────────────────────────────┬─────────────────────────────────────────────────────┐ │ Balance │ Value (0G) │ ├──────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤ │ Total │ 8.822778129999999663 │ ├──────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤ │ Locked (transferred to sub-accounts) │ 8.257334240000000491 │ ├──────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤ │ Available for transfer to sub-accounts │ 0.265443889999999960 │ └──────────────────────────────────────────────────┴─────────────────────────────────────────────────────┘ Inference sub-accounts ┌────────────────────────┬──────────────────────────────┬────────────────────────────────────────────────┐ │ Provider │ Balance (0G) │ Requested Return to Main Account (0G) │ ├────────────────────────┼──────────────────────────────┼────────────────────────────────────────────────┤ │ 0x924A2c71... │ 3.257334240000000047 │ 0.000000000000000000 │ ├────────────────────────┼──────────────────────────────┼────────────────────────────────────────────────┤ │ 0x960E74Fc... │ 3.000000000000000000 │ 3.000000000000000000 │ ├────────────────────────┼──────────────────────────────┼────────────────────────────────────────────────┤ │ 0x4f371f6e... │ 3.299999999999999822 │ 0.000000000000000000 │ └────────────────────────┴──────────────────────────────┴────────────────────────────────────────────────┘ ``` #### Transfer to Provider Before using a provider's service, transfer funds to their sub-account: ```bash 0g-compute-cli transfer-fund --provider --amount 5 ``` #### Request Refund Withdraw unused funds from sub-accounts back to main account: ```bash 0g-compute-cli retrieve-fund ``` **Note**: Refunds have a 24-hour lock period for security. After the lock period expires, you need to call this function again to complete the refund and transfer the funds back to your main account. You can check the remaining lock time using the `get-sub-account` command: ```bash 0g-compute-cli get-sub-account --provider ``` Example output showing refund details: ```text Details of Each Amount Applied for Return to Main Account ┌──────────────────────────────────────────────────┬──────────────────────────────────────────────────┐ │ Amount (0G) │ Remaining Locked Time │ ├──────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ │ 0.099785050000000000 │ 23h 43min 15s │ └──────────────────────────────────────────────────┴──────────────────────────────────────────────────┘ ``` #### Withdraw to Wallet Withdraw funds from main account to your wallet: ```bash 0g-compute-cli refund --amount 5 ``` **Best for:** Application integration and programmatic access ### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk ``` ### Initialize Broker ```typescript import { ethers } from "ethers"; import { createZGComputeNetworkBroker } from "@0gfoundation/0g-compute-ts-sdk"; const provider = new ethers.JsonRpcProvider("https://evmrpc-testnet.0g.ai"); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider); const broker = await createZGComputeNetworkBroker(wallet); ``` ### Check Account Balance ```typescript const account = await broker.ledger.getLedger(); console.log(`Total Balance: ${ethers.formatEther(account.totalBalance)} 0G`); console.log(`Available: ${ethers.formatEther(account.availableBalance)} 0G`); ``` ### Deposit Funds ```typescript await broker.ledger.depositFund(10); // Deposit 10 0G ``` ### Transfer to Provider ```typescript const providerAddress = ""; const amount = ethers.parseEther("5"); // 5 0G await broker.ledger.transferFund(providerAddress, "inference", amount); ``` ### Check Sub-Account Details ```typescript const [subAccount, refunds] = await broker.inference.getAccountWithDetail(providerAddress); console.log(`Sub-account balance: ${ethers.formatEther(subAccount.balance)} 0G`); const { account: subAccount, refunds } = await broker.fineTuning.getAccountWithDetail(providerAddress); console.log(`Sub-account balance: ${ethers.formatEther(subAccount.balance)} 0G`); ``` ### Request Refund ```typescript await broker.ledger.retrieveFund("inference"); await broker.ledger.retrieveFund("fine-tuning"); ``` ### Withdraw to Wallet ```typescript await broker.ledger.refund(5); // Withdraw 5 0G ``` --- ## Best Practices ### For Inference Services 1. Deposit enough funds for expected usage 2. Transfer funds to providers you plan to use frequently 3. Keep some balance in sub-accounts for better response times 4. Monitor usage regularly ### For Fine-tuning Services 1. Calculate dataset size before transferring funds 2. Transfer enough to cover the entire training job 3. Request refunds for unused funds after job completion ## Troubleshooting
Insufficient Balance Error Check which account needs funds: - Main account: Use `deposit` - Sub-account: Use `transfer-fund` ```bash # Check all balances 0g-compute-cli get-account # Deposit to main account if needed 0g-compute-cli deposit --amount 10 # Transfer to provider if needed 0g-compute-cli transfer-fund --provider
--amount 5 ```
Refund Not Available Refunds have a 24-hour lock period. After the lock period expires, you need to call the retrieve-fund function again to complete the refund. Check the status: ```bash 0g-compute-cli get-sub-account --provider ``` Look for "Remaining Locked Time" in the output.
Transaction Failed Common causes: 1. Network issues - Check your RPC endpoint 2. Gas price too low - Increase gas price 3. Insufficient gas - Ensure wallet has enough for gas fees ```bash # Specify custom gas price 0g-compute-cli deposit --amount 10 --gas-price 20000000000 ```
## Related Documentation - [Inference Services](./inference) - Using AI inference with your funded accounts - [Fine-tuning Services](./fine-tuning) - Training custom models with your funded accounts --- ## Fine-tuning Provider Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/fine-tuning-provider.md This guide provides a comprehensive walkthrough for setting up and offering computing power as a fine-tuning provider on the 0G Compute Network. ## Prerequisites - Docker and Docker Compose - TDX-enabled Intel CPU - Compatible NVIDIA GPU (H100/H200 with TEE support) - Wallet with 0G tokens for gas fees - Publicly accessible server ## Preparation ### Download the Installation Package - **Visit the Releases Page:** [0G Serving Broker Releases](https://github.com/0gfoundation/0g-compute-ts-sdk/releases) - **Download and Extract:** Get the latest version of the fine-tuning installation package. ### Configuration Setup **Copy the Config File:** Duplicate `config.example.yaml` to create `config.local.yaml`. ```bash cp config.example.yaml config.local.yaml ``` **Modify Settings:** - Set `servingUrl` to your publicly accessible URL. - Set `privateKeys` using your wallet's private key for the 0G blockchain. **Edit `docker-compose.yml`:** Replace `#PORT#` with the desired port, matching the port in `config.local.yaml`. ```bash # Replace #PORT# with your service port sed -i 's/#PORT#/8080/g' docker-compose.yml ``` ### Supporting Custom Models from Providers To include custom models, refer to the example configuration below and update your `config.local.yaml` file accordingly. Ensure that all required fields are properly defined to match your specific model setup. ```yaml service: customizedModels: - name: "deepseek-r1-distill-qwen-1.5b" hash: "" image: "deepseek:latest" dataType: "text" trainingScript: "/app/finetune.py" description: "DeepSeek-R1-Zero, a model trained via large-scale reinforcement learning (RL) without supervised fine-tuning (SFT) as a preliminary step, demonstrated remarkable performance on reasoning." tokenizer: "" usageFile: "" - name: "mobilenet_v2" hash: "" image: "mobilenetV2:latest" dataType: "image" trainingScript: "/app/finetune.py" description: "MobileNet V2 model pre-trained on ImageNet-1k at resolution 224x224." tokenizer: "" usageFile: "" ``` **Configuration Fields:** - **name:** Model identifier - **hash:** The root hash of the pre-trained model, obtained after uploading the model to 0G storage. - **image:** The Docker image that encapsulates the fine-tuning execution environment. - **dataType:** Specifies the type of dataset the model is intended to train on. Valid options include `text` or `image`. - **trainingScript:** Specifies the path to the training script within the container. Fine-tuning will be executed using the command `python `. - **description:** A concise overview of the model, highlighting its key features and capabilities. - **tokenizer:** The root hash of the tokenizer files used for dataset processing. This value is obtained after uploading the tokenizer files to 0G storage. - **usageFile:** The ZIP file (referenced by its name, not the full path) contains detailed usage information for this model, including training configuration examples, build specifications, or sample datasets. Make sure the file is placed in the `./models` directory. ## Build the TDX Guest Image ### Prerequisites Installation **Install Docker:** ```bash curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh ``` **Add User to Docker Group:** ```bash sudo usermod -aG docker $USER newgrp docker ``` **Verify Installation:** ```bash docker --version docker run hello-world ``` ### Build CVM Image To ensure secure and private execution of fine-tuning tasks, you will build an image suitable for running in a Confidential Virtual Machine (CVM). This process leverages NVIDIA's TEE GPU technology and Intel CPUs with TDX support, enhancing security by running model training in an isolated environment. **Clone Repository:** ```bash git clone https://github.com/nearai/private-ml-sdk --recursive cd private-ml-sdk/ ./build.sh ``` **Image Files Location:** Check out `private-ml-sdk/images/`. Available images include: - `dstack-nvidia-0.3.0`: Production image without developer tools. - `dstack-nvidia-dev-0.3.0`: Development image with tools like `sshd`, `strace`. ## Run Application ### Run the Local KMS The Local KMS provides essential keys for CVM initialization, derived from local TEE hardware. **Launch KMS:** ```bash cd private-ml-sdk/meta-dstack-nvidia/dstack/key-provider-build/ ./run.sh ``` ### Run the TDX Guest Image Ensure you have a TDX host machine with the TDX driver and a compatible NVIDIA GPU. **Update PATH:** ```bash pushd private-ml-sdk/meta-dstack-nvidia/scripts/bin PATH=$PATH:`pwd` popd ``` **List Available GPUs:** ```bash dstack lsgpu ``` **Create CVM Instance:** Replace `#PORT#` with your configured port: ```bash dstack new docker-compose.yaml -o my-gpu-cvm \ --local-key-provider \ --gpu [GPU_ID] \ --image images/dstack-nvidia-0.3.0 \ -c 2 -m 4G -d 100G \ --port tcp:0.0.0.0:#PORT#:#PORT# ``` ### Run the CVM **Copy Config File:** ```bash cp config.local.yaml private-ml-sdk/my-gpu-cvm/shared/config.local.yaml ``` **Start the CVM:** ```bash sudo -E dstack run my-gpu-cvm ``` ## Troubleshooting
CVM fails to start - Verify TDX is enabled in BIOS - Check GPU compatibility and drivers - Ensure sufficient resources allocated - Review logs: `sudo dstack logs my-gpu-cvm`
Service not accessible - Confirm firewall allows incoming connections - Verify public IP/domain configuration - Check port consistency between config and Docker - Test local connectivity first
Model upload issues - Ensure model files are uploaded to 0G storage - Verify root hash is correctly configured - Check tokenizer files are included - Confirm Docker image exists and is accessible
--- *By following these steps, you will successfully set up your service as a fine-tuning provider on the 0G Compute Network, leveraging secure and verifiable computing environments.* --- ## Fine-tuning Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/fine-tuning.md Customize AI models with your own data using 0G's distributed GPU network. ## Quick Start ### Prerequisites Node version >= 22.0.0 ### Install CLI ```bash pnpm install @0gfoundation/0g-compute-ts-sdk -g ``` ### Set Environment #### Choose Network ```bash # Setup network 0g-compute-cli setup-network ``` #### Login with Wallet Enter your wallet private key when prompted. ```bash # Login with your wallet private key 0g-compute-cli login ``` ### Create Account & Add Funds The Fine-tuning CLI requires an account to pay for service fees via the 0G Compute Network. **For detailed account management instructions, see [Account](./account-management).** ```bash # Deposit funds to your account 0g-compute-cli deposit --amount 3 # Transfer funds to a provider for fine-tuning # IMPORTANT: You must specify --service fine-tuning, otherwise funds go to the inference sub-account 0g-compute-cli transfer-fund --provider --amount 2 --service fine-tuning ``` :::tip If you see `MinimumDepositRequired` when creating a task, it means you haven't transferred funds to the provider's **fine-tuning** sub-account. Make sure to include `--service fine-tuning` in the `transfer-fund` command. ::: ### List Providers ```bash 0g-compute-cli fine-tuning list-providers ``` The output will be like: ```bash ┌──────────────────────────────────────────────────┬──────────────────────────────────────────────────┐ │ Provider 1 │ 0x940b4a101CaBa9be04b16A7363cafa29C1660B0d │ ├──────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ │ Available │ ✓ │ └──────────────────────────────────────────────────┴──────────────────────────────────────────────────┘ ``` - **Provider x:** The address of the provider. - **Available:** Indicates if the provider is available. If `✓`, the provider is available. If `✗`, the provider is occupied. ### List Models ```bash # List available models 0g-compute-cli fine-tuning list-models ```
📋 Available Models Summary The CLI displays two categories of models: predefined models available across all providers and provider-specific models with unique capabilities. #### Predefined Models These are standard models available across all providers: | Model Name | Type | Price per Million Tokens | Description | |------------|------|--------------------------|-------------| | `Qwen2.5-0.5B-Instruct` | Causal LM | 0.5 0G | Qwen 2.5 instruction-tuned model (0.5B parameters). More details: [HuggingFace](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct) | | `Qwen3-32B` | Causal LM | 4 0G | Qwen 3 large language model (32B parameters). More details: [HuggingFace](https://huggingface.co/Qwen/Qwen3-32B) |
The output consists of two main sections: - **Predefined Models:** Models provided by the system as predefined options. They are built-in, curated, and maintained to ensure quality and reliability. - **Provider's Model:** Models offered by external service providers. Providers may customize or fine-tune models to address specific needs. :::caution Model Name Format Use model names **without** the `Qwen/` prefix when specifying the `--model` parameter. For example: - ✅ `--model "Qwen2.5-0.5B-Instruct"` - ❌ `--model "Qwen/Qwen2.5-0.5B-Instruct"` ::: ### Prepare Configuration File Use the standard configuration template below and **only modify the parameter values** as needed. Do not add additional parameters. #### Standard Configuration Template ```json { "neftune_noise_alpha": 5, "num_train_epochs": 1, "per_device_train_batch_size": 2, "learning_rate": 0.0002, "max_steps": 3 } ``` :::caution Important Configuration Rules 1. **Use the template above** - Copy the entire template 2. **Only modify parameter values** - Do not add or remove parameters 3. **Use decimal notation** - Write `0.0002` instead of `2e-4` for `learning_rate` **Common mistakes to avoid:** - ❌ Adding extra parameters (e.g., `"fp16": true`, `"bf16": false`) - ❌ Removing existing parameters - ❌ Using scientific notation like `2e-4` ::: #### Adjustable Parameters You can modify these parameter values based on your training needs: | Parameter | Description | Notes | |-----------|-------------|-------| | `neftune_noise_alpha` | Noise injection for fine-tuning | 0-10 (0 = disabled), typical: 5 | | `num_train_epochs` | Number of complete passes through the dataset | Positive integer, typical: 1-3 for fine-tuning | | `per_device_train_batch_size` | Training batch size | 1-4, reduce to 1 if out of memory | | `learning_rate` | Learning rate (use decimal notation) | 0.00001-0.001, typical: 0.0002 | | `max_steps` | Maximum training steps | -1 (use epochs) or positive integer | :::tip GPU Memory Management - If you encounter out-of-memory errors, **reduce batch size to 1** - The provider automatically handles mixed precision training with `bf16` ::: *Note:* For custom models provided by third-party Providers, you can download the usage template including instructions on how to construct the dataset and training configuration using the following command: ```bash 0g-compute-cli fine-tuning model-usage --provider --model --output ``` ### Prepare Your Data Your dataset must be in **JSONL format** with a **`.jsonl` file extension**. Each line is a JSON object representing one training example. #### Supported Dataset Formats **Format 1: Instruction-Input-Output** ```json {"instruction": "Translate to French", "input": "Hello world", "output": "Bonjour le monde"} {"instruction": "Translate to French", "input": "Good morning", "output": "Bonjour"} {"instruction": "Summarize the text", "input": "Long article...", "output": "Brief summary"} ``` **Format 2: Chat Messages** ```json {"messages": [{"role": "user", "content": "What is 2+2?"}, {"role": "assistant", "content": "2+2 equals 4."}]} {"messages": [{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there! How can I help you?"}]} ``` **Format 3: Simple Text (for text completion)** ```json {"text": "The quick brown fox jumps over the lazy dog."} {"text": "Machine learning is a subset of artificial intelligence."} ``` #### Dataset Guidelines - **File format**: Must be a `.jsonl` file (JSONL format) - **Minimum examples**: At least 10 examples recommended for meaningful fine-tuning - **Quality**: Ensure examples are accurate and representative of your use case - **Consistency**: Use the same format throughout the dataset - **Encoding**: UTF-8 encoding required ### Create Task Create a fine-tuning task. The fee will be **automatically calculated** by the broker based on the actual token count of your dataset. **Option A: Using local dataset file (Recommended)** The CLI will automatically upload the dataset to 0G Storage and create the task in one step: ```bash 0g-compute-cli fine-tuning create-task \ --provider \ --model \ --dataset-path \ --config-path ``` **Option B: Using dataset root hash** If you prefer to upload the dataset separately first, or need to reuse the same dataset: 1. Upload your dataset to 0G Storage: ```bash 0g-compute-cli fine-tuning upload --data-path ``` Output: ```bash Root hash: 0xabc123... ``` 2. Create the task using the root hash: ```bash 0g-compute-cli fine-tuning create-task \ --provider \ --model \ --dataset \ --config-path ``` **Parameters:** | Parameter | Description | |-----------|-------------| | `--provider` | Address of the service provider | | `--model` | Name of the pretrained model (without `Qwen/` prefix) | | `--dataset-path` | Path to local dataset file — automatically uploads to 0G Storage (Option A) | | `--dataset` | Root hash of the dataset on 0G Storage — mutually exclusive with `--dataset-path` (Option B) | | `--config-path` | Path to the training configuration file | | `--gas-price` | Gas price (optional) | The output will be like: ```bash Verify provider... Provider verified Creating task (fee will be calculated automatically)... Fee will be automatically calculated by the broker based on actual token count Created Task ID: 6b607314-88b0-4fef-91e7-43227a54de57 ``` *Note:* When creating a task for the same provider, you must wait for the previous task to be completed (status `Finished`) before creating a new task. If the provider is currently running other tasks, you will be prompted to choose between adding your task to the waiting queue or canceling the request. ### Fee Calculation The fine-tuning service fee is **automatically calculated** based on your dataset size and training configuration. The fee consists of two components: #### Formula ```text Total Fee = Training Fee + Storage Reserve Fee ``` Where: - **Training Fee** = `(tokenSize / 1,000,000) × pricePerMillionTokens × trainEpochs` - **Storage Reserve Fee** = Fixed amount based on model size #### Components Explained | Component | Description | |-----------|-------------| | `tokenSize` | Total number of tokens in your dataset (automatically counted) | | `pricePerMillionTokens` | Price per million tokens (model-specific, see [Predefined Models](#predefined-models)) | | `trainEpochs` | Number of training epochs (from your config) | | `Storage Reserve Fee` | Fixed fee to reserve storage for the fine-tuned model:• Qwen3-32B (~900 MB LoRA): 0.09 0G• Qwen2.5-0.5B-Instruct (~100 MB LoRA): 0.01 0G | #### Example For a dataset with 10,000 tokens, trained for 3 epochs on Qwen2.5-0.5B-Instruct: - Price per million tokens = 0.5 0G (see [Predefined Models](#predefined-models)) - Training Fee = (10,000 / 1,000,000) × 0.5 × 3 = 0.015 0G - Storage Reserve Fee = 0.01 0G (for Qwen2.5-0.5B-Instruct) - **Total Fee = 0.025 0G** :::tip The actual fee is calculated during the setup phase after your dataset is analyzed. You can view the final fee using the [`get-task`](#monitor-progress) command before training begins. ::: ### Monitor Progress You can monitor the progress of your task by running the following command: ```bash 0g-compute-cli fine-tuning get-task --provider --task ``` The output will be like: ```bash ┌───────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┐ │ Field │ Value │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ ID │ beb6f0d8-4660-4c62-988d-00246ce913d2 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Created At │ 2025-03-11T01:20:07.644Z │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Pre-trained Model Hash │ 0xcb42b5ca9e998c82dd239ef2d20d22a4ae16b3dc0ce0a855c93b52c7c2bab6dc │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Dataset Hash │ 0xaae9b4e031e06f84b20f10ec629f36c57719ea512992a6b7e2baea93f447a5fa │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Training Params │ {......} │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Fee (neuron) │ 82 │ ├───────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ Progress │ Delivered │ └───────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┘ ``` **Field Descriptions:** - **ID**: Unique identifier for your fine-tuning task - **Pre-trained Model Hash**: Hash identifier for the base model being fine-tuned - **Dataset Hash**: Hash identifier for your training dataset (0G Storage root hash) - **Training Params**: Configuration parameters used during fine-tuning - **Fee (neuron)**: Total cost for the fine-tuning task (automatically calculated based on token count) - **Progress**: Task status. Possible values are: - `Init`: Task submitted - `SettingUp`: Provider is preparing the environment (downloading dataset, etc.) - `SetUp`: Provider is ready to start training - `Training`: Provider is training the model - `Trained`: Provider has finished training - `Delivering`: Provider is encrypting and uploading the model to 0G Storage - `Delivered`: Fine-tuning result is ready for download - `UserAcknowledged`: User has downloaded and confirmed the result - `Finished`: Provider has settled fees and shared decryption key — task is completed - `Failed`: Task failed ### View Task Logs You can view the logs of your task by running the following command: ```bash 0g-compute-cli fine-tuning get-log --provider --task ``` The output will be like: ```bash creating task.... Step: 0, Logs: {'loss': ..., 'accuracy': ...} ... Training model for task beb6f0d8-4660-4c62-988d-00246ce913d2 completed successfully ``` ### Download and Acknowledge Model Use the [Check Task](#monitor-progress) command to view task status. When the status changes to `Delivered`, the provider has completed fine-tuning and the encrypted model is ready. Download and acknowledge the model: ```bash 0g-compute-cli fine-tuning acknowledge-model \ --provider \ --task-id \ --data-path ``` The CLI will automatically download the encrypted model from 0G Storage. If 0G Storage download fails, it will fall back to downloading directly from the provider's TEE. :::danger 48-Hour Deadline **You must download and acknowledge the model within 48 hours after the task status changes to `Delivered`.** If you fail to acknowledge within 48 hours: - The provider will **force settlement** automatically - You will **lose access to the fine-tuned model** - **30% of the total task fee** will be deducted as compensation for the provider's compute resources **Action required:** Monitor your task status and download promptly when it reaches `Delivered`. ::: :::caution File Path Required `--data-path` **must be a file path**, not a directory. **Example:** ```bash 0g-compute-cli fine-tuning acknowledge-model \ --provider \ --task-id 0e91ef3d-ac0d-422e-a38c-9d42a28c4412 \ --data-path /workspace/output/encrypted_model.bin ``` ::: :::tip Data Integrity Verification The `acknowledge-model` command performs automatic data integrity verification to ensure the downloaded model matches the root hash that the provider submitted to the blockchain contract. This guarantees you receive the authentic model without corruption or tampering. ::: **Note:** The model file downloaded with the above command is encrypted, and additional steps are required for decryption. ### Decrypt Model After acknowledging the model, the provider automatically settles the fees and uploads the decryption key to the contract (encrypted with your public key). Use the `get-task` command to check the task status. **When the status changes to `Finished`**, you can decrypt the model: ```bash 0g-compute-cli fine-tuning decrypt-model \ --provider \ --task-id \ --encrypted-model \ --output ``` **Example:** ```bash # Use the same file path you specified in acknowledge-model 0g-compute-cli fine-tuning decrypt-model \ --provider \ --task-id 0e91ef3d-ac0d-422e-a38c-9d42a28c4412 \ --encrypted-model /workspace/output/encrypted_model.bin \ --output /workspace/output/model_output.zip ``` The above command performs the following operations: - Gets the encrypted key from the contract uploaded by the provider - Decrypts the key using the user's private key - Decrypts the model with the decrypted key :::caution Wait for Settlement After `acknowledge-model`, the provider needs about **1 minute** to settle fees and upload the decryption key. If you decrypt too early (status is still `UserAcknowledged` instead of `Finished`), you may see an error like `second arg must be public key`. Simply wait and retry. ::: **Note:** The decrypted result will be saved as a zip file. Ensure that the `` ends with .zip (e.g., model_output.zip). After downloading, unzip the file to access the decrypted model. ### Extract LoRA Adapter After decryption, unzip the model to access the LoRA adapter files: ```bash unzip model_output.zip -d ./lora_adapter/ ``` The extracted folder will contain: ```text lora_adapter/ ├── output_model/ │ ├── adapter_config.json # LoRA configuration │ ├── adapter_model.safetensors # LoRA weights │ ├── tokenizer.json # Tokenizer │ ├── tokenizer_config.json │ └── README.md ``` ## Using the Fine-tuned Model After fine-tuning, you receive a **LoRA adapter** (Low-Rank Adaptation), not a full model. To use it, you need to: 1. Download the base model 2. Load the LoRA adapter on top of the base model 3. Run inference ### Step 1: Download Base Model Download the same base model that was used for fine-tuning from HuggingFace: ```bash # Install huggingface-cli if not already installed pip install huggingface_hub # For Qwen2.5-0.5B-Instruct huggingface-cli download Qwen/Qwen2.5-0.5B-Instruct --local-dir ./base_model # For Qwen3-32B (requires ~65GB disk space) # huggingface-cli download Qwen/Qwen3-32B --local-dir ./base_model ``` ### Step 2: Load LoRA with Base Model Use the following Python code to combine the LoRA adapter with the base model. **For Qwen2.5-0.5B-Instruct:** ```python from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel import torch # Paths base_model_path = "./base_model" # or "Qwen/Qwen2.5-0.5B-Instruct" lora_adapter_path = "./lora_adapter/output_model" # Load tokenizer tokenizer = AutoTokenizer.from_pretrained(lora_adapter_path) # Load base model base_model = AutoModelForCausalLM.from_pretrained( base_model_path, torch_dtype=torch.bfloat16, device_map="auto" ) # Load LoRA adapter model = PeftModel.from_pretrained(base_model, lora_adapter_path) print("Model loaded successfully!") ``` **For Qwen3-32B (requires 40GB+ VRAM):** ```python from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel import torch # Paths base_model_path = "./base_model" # or "Qwen/Qwen3-32B" lora_adapter_path = "./lora_adapter/output_model" # Load tokenizer tokenizer = AutoTokenizer.from_pretrained(lora_adapter_path) # Load base model with optimizations for large models base_model = AutoModelForCausalLM.from_pretrained( base_model_path, torch_dtype=torch.float16, # Use fp16 to reduce memory device_map="auto", # Automatically distribute across GPUs low_cpu_mem_usage=True, # Reduce CPU memory usage during loading trust_remote_code=True # Required for some Qwen models ) # Load LoRA adapter model = PeftModel.from_pretrained(base_model, lora_adapter_path) print("Model loaded successfully!") ``` :::tip Memory Optimization for Large Models If you encounter out-of-memory errors with Qwen3-32B, you can use quantization: ```python # 8-bit quantization (requires bitsandbytes) from transformers import BitsAndBytesConfig quantization_config = BitsAndBytesConfig(load_in_8bit=True) base_model = AutoModelForCausalLM.from_pretrained( base_model_path, quantization_config=quantization_config, device_map="auto", trust_remote_code=True ) ``` ::: ### Step 3: Run Inference ```python def generate_response(prompt, max_new_tokens=100): messages = [{"role": "user", "content": prompt}] # Apply chat template text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) # Tokenize inputs = tokenizer(text, return_tensors="pt").to(model.device) # Generate outputs = model.generate( **inputs, max_new_tokens=max_new_tokens, do_sample=True, temperature=0.7, top_p=0.9 ) # Decode response = tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True) return response # Example usage response = generate_response("Hello, how are you?") print(response) ``` ### Optional: Merge and Save Full Model If you want to create a standalone model without needing to load the adapter separately: ```python from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel import torch # Load base model and LoRA base_model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen2.5-0.5B-Instruct", torch_dtype=torch.bfloat16, device_map="auto" ) model = PeftModel.from_pretrained(base_model, "./lora_adapter/output_model") # Merge LoRA weights into base model merged_model = model.merge_and_unload() # Save the merged model merged_model.save_pretrained("./merged_model") tokenizer = AutoTokenizer.from_pretrained("./lora_adapter/output_model") tokenizer.save_pretrained("./merged_model") print("Merged model saved to ./merged_model") ``` ### Requirements Install the required Python packages: #### For GPU Environments (Recommended) If you have an NVIDIA GPU, install PyTorch with CUDA support. **Important:** Match the CUDA version to your environment. ```bash # For CUDA 12.1 (check your CUDA version with: nvidia-smi) pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 # For CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # Install other ML libraries pip install transformers peft accelerate ``` #### For CPU-Only Environments ```bash pip install torch transformers peft accelerate ``` #### Package Requirements | Package | Minimum Version | Purpose | |---------|-----------------|---------| | `torch` | >= 2.0 | Deep learning framework | | `transformers` | >= 4.40.0 | Model loading and inference | | `peft` | >= 0.10.0 | LoRA adapter support | | `accelerate` | >= 0.27.0 | Device management | :::tip Verify GPU Support After installation, verify that PyTorch can detect your GPU: ```bash python3 -c "import torch; print('PyTorch version:', torch.__version__); print('CUDA available:', torch.cuda.is_available())" ``` If `CUDA available: False`, you may need to reinstall PyTorch with the correct CUDA version. ::: ### Account Management For comprehensive account management, including viewing balances, managing sub-accounts, and handling refunds, see [Account](./account-management). Quick CLI commands: ```bash # Check balance 0g-compute-cli get-account # View sub-account for a provider 0g-compute-cli get-sub-account --provider # Request refund from sub-accounts 0g-compute-cli retrieve-fund ``` ### Other Commands #### Upload Dataset Separately You can upload a dataset to 0G Storage before creating a task: ```bash 0g-compute-cli fine-tuning upload --data-path ``` #### Download Data You can download previously uploaded datasets from 0G Storage: ```bash 0g-compute-cli fine-tuning download --data-path --data-root ``` #### View Task List You can view the list of tasks submitted to a specific provider using the following command: ```bash 0g-compute-cli fine-tuning list-tasks --provider ``` #### Cancel a Task You can cancel a task before it starts running using the following command: ```bash 0g-compute-cli fine-tuning cancel-task --provider --task ``` **Note:** Tasks that are already in progress or completed cannot be canceled. ## Troubleshooting
Error: MinimumDepositRequired This means the provider's fine-tuning sub-account has insufficient funds. Make sure to include `--service fine-tuning` when transferring funds: ```bash 0g-compute-cli transfer-fund --provider --amount 2 --service fine-tuning ```
Error: Provider busy The provider is processing another task. Options: 1. Wait and retry later 2. Use a different provider: `0g-compute-cli fine-tuning list-providers` 3. Queue your task (you'll be prompted)
Error: Insufficient balance Add more funds: ```bash 0g-compute-cli deposit --amount 3 0g-compute-cli transfer-fund --provider --amount 2 --service fine-tuning ```
Error: "second arg must be public key" when decrypting This means the provider hasn't finished settlement yet. Wait about 1 minute after `acknowledge-model`, then check the task status: ```bash 0g-compute-cli fine-tuning get-task --provider --task ``` When `Progress` shows `Finished`, retry the `decrypt-model` command.
Error: "Unexpected non-whitespace character after JSON" when creating task Check your training configuration JSON file: - Ensure valid JSON format - Use decimal notation for numbers (e.g., `0.0002` instead of `2e-4`) - Verify no trailing commas
--- ## Inference Provider Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference-provider.md Transform your AI services into verifiable, revenue-generating endpoints on the 0G Compute Network. This guide covers setting up your service and connecting it through the provider broker. ## Why Become a Provider? - **Monetize Your Infrastructure**: Turn idle GPU resources into revenue - **Automated Settlements**: The broker handles billing and payments automatically - **Trust Through Verification**: Offer verifiable services for premium rates ## Prerequisites - Docker Compose 1.27+ - OpenAI-compatible model service - Wallet with 0G tokens for gas fees ## Setup Process ### Prepare Your Model Service #### Service Interface Requirements Your AI service must implement the [OpenAI API Interface](https://developers.openai.com/api/reference/chat-completions/overview) for compatibility. This ensures consistent user experience across all providers. #### Verification Interfaces To ensure the integrity and trustworthiness of services, different verification mechanisms are employed. Each mechanism comes with its own specific set of protocols and requirements to ensure service verification and security. TEE (Trusted Execution Environment) verification ensures your computations are tamper-proof. Services running in TEE: - Generate signing keys within the secure environment - Provide CPU and GPU attestations - Sign all inference results These attestations should include the public key of the signing key, verifying its creation within the TEE. All inference results must be signed with this signing key. ### Hardware Requirements - **CPU**: Intel TDX (Trusted Domain Extensions) enabled - **GPU**: NVIDIA H100 or H200 with TEE support ### TEE Node Setup There are two ways to start a TEE node for your inference service: #### Method 1: Using Dstack Follow the [Dstack Getting Started Guide](https://github.com/Dstack-TEE/dstack?tab=readme-ov-file#-getting-started) to prepare your TEE node using Dstack. #### Method 2: Using Cryptopilot Follow the [0G-TAPP README](https://github.com/0gfoundation/0g-tapp/blob/main/README.md) to set up your TEE node using Cryptopilot. ### Download and Configure Inference Broker To register and manage TEE services, handle user request proxies, and perform settlements, you need to use the Inference Broker. Please visit the [releases page](https://github.com/0gfoundation/0g-compute-ts-sdk/releases) to download and extract the latest version of the installation package. After extracting, use the executable `config` file to generate the configuration file and docker-compose.yml file according to your setup. ```bash # Download from releases page tar -xzf inference-broker.tar.gz cd inference-broker # Generate configuration files ./config ``` Support for additional verification methods including: - **OPML**: Optimistic Machine Learning proofs - **ZKML**: Zero-knowledge ML verification Stay tuned for updates. ### Launch Provider Broker Follow the instructions in [Dstack](https://github.com/Dstack-TEE/dstack?tab=readme-ov-file#-getting-started) or [0G-TAPP](https://github.com/0gfoundation/0g-tapp/blob/main/README.md) documentation to start the service using the config file and docker-compose.yml file generated in the previous step. The broker will: - Register your service on the network - Handle user authentication and request routing - Manage automatic settlement of payments ## Troubleshooting
Broker fails to start - Verify Docker Compose is installed correctly - Check port availability - Ensure config.local.yaml syntax is valid - Review logs: `docker compose logs`
Service not accessible - Confirm firewall allows incoming connections - Verify public IP/domain is correct - Test local service: `curl http://localhost:8000/chat/completions`
Settlement issues The automatic settlement engine handles payments. If issues occur: - Check wallet has sufficient gas - Verify network connectivity - Monitor settlement logs in broker output
## Next Steps - **Join Community** → [Discord](https://discord.gg/0glabs) for support - **Explore Inference** → [Inference Documentation](./inference) for integration details --- ## Inference Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/inference.md Run inference by connecting to individual 0G Compute providers via the `@0gfoundation/0g-compute-ts-sdk` SDK. You manage per-provider sub-accounts and sign every request with your wallet. For fine-tuning via the same SDK see [Fine-tuning](./fine-tuning); for funding and sub-account management see [Account](./account-management). :::tip Not sure which path to use? 0G Compute offers **two ways** to run inference: - **[Router](./router/overview)** *(recommended for most applications)* — a single OpenAI-compatible API endpoint with one unified balance, automatic provider failover, and an API key. Use this if you're building a server-side app, agent, or prototype. - **Direct** *(this page)* — connect to individual providers, manage per-provider sub-accounts, and sign requests with your wallet. Use this for browser dApps with wallet signing or when you need direct on-chain control. Side-by-side comparison: [Router vs Direct](./router/comparison). ::: :::note If your balance on pc.0g.ai looks empty The default **Router** view on [pc.0g.ai](https://pc.0g.ai) shows the Router balance, which is a separate on-chain pool from the per-provider sub-accounts described on this page. To see funds you've deposited on [compute-marketplace.0g.ai](https://compute-marketplace.0g.ai) (or through the CLI/SDK below), switch to **Advanced** mode using the top-right toggle on pc.0g.ai — it's the same Direct flow embedded in the new UI. ::: ## Prerequisites - Node.js >= 20.0.0 - A wallet with 0G tokens (either testnet or mainnet) - EVM compatible wallet (for Web UI) ## Supported Service Types - **Chatbot Services**: Conversational AI with models like GPT, DeepSeek, and others - **Text-to-Image**: Generate images from text descriptions using Stable Diffusion and similar models - **Speech-to-Text**: Transcribe audio to text using Whisper and other speech recognition models ## Available Services The provider and model catalog changes frequently (providers join and leave, pricing is set per-provider). This page does not reproduce the list — check a live source instead: - **Web UI** — [pc.0g.ai](https://pc.0g.ai) (switch to **Advanced** mode, top-right) or [compute-marketplace.0g.ai/inference](https://compute-marketplace.0g.ai/inference) — both show the current provider catalog with pricing, health, and TEE attestation - **CLI** — `0g-compute-cli inference list-providers` - **SDK** — `await broker.inference.listService()` ### Verification modes Each service declares one of two TEE verification modes: **TeeML** — The AI model runs directly inside a Trusted Execution Environment. The TEE guarantees that both the model and the computation are protected, and responses are signed by the TEE's private key. Used by self-hosted models. **TeeTLS** — The Broker runs inside a TEE and proxies requests to a centralized LLM provider over HTTPS. This provides cryptographic proof that responses genuinely came from the real provider: - **Authentic routing**: During the TLS handshake, the Broker verifies the provider's certificate against trusted Certificate Authorities, ensuring the connection reaches the real provider — not an imposter. - **Cryptographic proof**: The Broker captures the provider's TLS certificate fingerprint and bundles it together with the request hash, response hash, and provider identity into a signed routing proof using its TEE-protected private key. - **Privacy preservation**: Since the Broker runs inside a TEE, it cannot inspect or tamper with user data in transit — 0G acts as a verifiable relay, not a middleman. This is conceptually similar to zkTLS but with stronger privacy properties, as the TEE ensures the relay itself is trustworthy. - **End-to-end integrity**: The TEE attestation proves the Broker is running unmodified code, the CA/TLS system guarantees only the real provider holds a valid certificate for their domain, and the TEE signature binds everything together — a verifier can confirm the proof came from a genuine TEE and that the fingerprint belongs to the expected provider. ## Choose Your Interface | Feature | Web UI | CLI | SDK | |---------|--------|-----|-----| | Setup time | ~1 min | ~2 min | ~5 min | | Interactive chat | ✅ | ❌ | ❌ | | Automation | ❌ | ✅ | ✅ | | App integration | ❌ | ❌ | ✅ | | Direct API access | ❌ | ❌ | ✅ | **Best for:** Quick testing, experimentation and direct frontend integration. ### Option 1: Use the Hosted Web UI Two hosted entry points — both run the same Direct flow against the same per-provider sub-accounts: - **[https://compute-marketplace.0g.ai/inference](https://compute-marketplace.0g.ai/inference)** — the original Marketplace UI - **[https://pc.0g.ai](https://pc.0g.ai)** with the top-right toggle set to **Advanced** — the same flow embedded in the new pc.0g.ai UI (the default "Router" mode on pc.0g.ai is a different, newer system — see the [Router docs](./router/overview)) ### Option 2: Run Locally #### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk -g ``` #### Launch Web UI ```bash 0g-compute-cli ui start-web ``` Open `http://localhost:3090` in your browser. ### Getting Started #### 1. Connect & Fund 1. **Connect your wallet** (MetaMask recommended) 2. **Deposit some 0G tokens** using the account dashboard 3. **Browse available AI models** and their pricing #### 2. Start Using AI Services **Option A: Chat Interface** - Click "Chat" on any chatbot provider - Start conversations immediately - Perfect for testing and experimentation **Option B: Get API Integration** - Click "Build" on any provider - Get step-by-step integration guides - Copy-paste ready code examples **Best for:** Automation, scripting, and server environments ### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk -g ``` ### Setup Environment #### Choose Network ```bash 0g-compute-cli setup-network ``` #### Login with Wallet Enter your wallet private key when prompted. This will be used for account management and service payments. ```bash 0g-compute-cli login ``` ### Create Account & Add Funds Before using inference services, you need to fund your account. For detailed account management, see [Account](./account-management). ```bash 0g-compute-cli deposit --amount 10 0g-compute-cli get-account 0g-compute-cli transfer-fund --provider --amount 1 ``` ### CLI Commands #### List Providers ```bash 0g-compute-cli inference list-providers ``` #### Verify Provider Check provider's TEE attestation and reliability before using: ```bash 0g-compute-cli inference verify --provider ``` This command outputs the provider's report and verifies their Trusted Execution Environment (TEE) status. #### Acknowledge Provider (Optional) If you already used `transfer-fund` to fund a provider, acknowledgement happens automatically. This command is only needed if you want to acknowledge without transferring funds: ```bash 0g-compute-cli inference acknowledge-provider --provider ``` #### Direct API Access Generate an authentication token for direct API calls: ```bash 0g-compute-cli inference get-secret --provider ``` This generates a Bearer token in the format `app-sk-` that you can use for direct API calls. ### API Usage Examples Use for conversational AI and text generation. ```bash curl /v1/proxy/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer app-sk-" \ -d '{ "model": , "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "Hello!" } ] }` ``` ```javascript const OpenAI = require('openai'); const client = new OpenAI({ baseURL: `${service.url}/v1/proxy`, apiKey: 'app-sk-' }); const completion = await client.chat.completions.create({ model: service.model, messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Hello!' } ] }); console.log(completion.choices[0].message); ``` ```python from openai import OpenAI client = OpenAI( base_url=`${service.url}/v1/proxy`, api_key='app-sk-' ) completion = client.chat.completions.create( model=service.model, messages=[ { 'role': 'system', 'content': 'You are a helpful assistant.' }, { 'role': 'user', 'content': 'Hello!' } ] ) print(completion.choices[0].message) ``` Generate images from text descriptions. ```bash curl /v1/proxy/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer app-sk-" \ -d '{ "model": , "prompt": "A cute baby sea otter playing in the water", "n": 1, "size": "1024x1024" }' ``` ```javascript const OpenAI = require('openai'); const client = new OpenAI({ baseURL: `${service.url}/v1/proxy`, apiKey: 'app-sk-' }); const response = await client.images.generate({ model: service.model, prompt: 'A cute baby sea otter playing in the water', n: 1, size: '1024x1024' }); console.log(response.data); ``` ```python from openai import OpenAI client = OpenAI( base_url=`${service.url}/v1/proxy`, api_key='app-sk-' ) response = client.images.generate( model=service.model, prompt='A cute baby sea otter playing in the water', n=1, size='1024x1024' ) print(response.data) ``` Transcribe audio files to text. ```bash curl /v1/proxy/audio/transcriptions \ -H "Authorization: Bearer app-sk-" \ -H "Content-Type: multipart/form-data" \ -F "file=@audio.ogg" \ -F "model=whisper-large-v3" \ -F "response_format=json" ``` ```javascript const OpenAI = require('openai'); const fs = require('fs'); const client = new OpenAI({ baseURL: `${service.url}/v1/proxy`, apiKey: 'app-sk-' }); const transcription = await client.audio.transcriptions.create({ file: fs.createReadStream('audio.ogg'), model: 'whisper-large-v3', response_format: 'json' }); console.log(transcription.text); ``` ```python from openai import OpenAI client = OpenAI( base_url=`${service.url}/v1/proxy`, api_key='app-sk-' ) with open('audio.ogg', 'rb') as audio_file: transcription = client.audio.transcriptions.create( file=audio_file, model='whisper-large-v3', response_format='json' ) print(transcription.text) ``` ### Start Local Proxy Server Run a local OpenAI-compatible server: ```bash # Start server on port 3000 (default) 0g-compute-cli inference serve --provider # Custom port 0g-compute-cli inference serve --provider --port 8080 ``` Then use any OpenAI-compatible client to connect to `http://localhost:3000`. **Best for:** Application integration and programmatic access ### Installation ```bash pnpm add @0gfoundation/0g-compute-ts-sdk ``` :::tip Starter Kits Available Get up and running quickly with our comprehensive TypeScript starter kit within minutes. - **[TypeScript Starter Kit](https://github.com/0gfoundation/0g-compute-ts-starter-kit)** - Complete examples with TypeScript and CLI tool ::: ### Initialize the Broker ```typescript import { ethers } from "ethers"; import { createZGComputeNetworkBroker } from "@0gfoundation/0g-compute-ts-sdk"; // Choose your network const RPC_URL = process.env.NODE_ENV === 'production' ? "https://evmrpc.0g.ai" // Mainnet : "https://evmrpc-testnet.0g.ai"; // Testnet const provider = new ethers.JsonRpcProvider(RPC_URL); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider); const broker = await createZGComputeNetworkBroker(wallet); ``` ```typescript import { BrowserProvider } from "ethers"; import { createZGComputeNetworkBroker } from "@0gfoundation/0g-compute-ts-sdk"; // Check if MetaMask is installed if (typeof window.ethereum === "undefined") { throw new Error("Please install MetaMask"); } const provider = new BrowserProvider(window.ethereum); const signer = await provider.getSigner(); const broker = await createZGComputeNetworkBroker(signer); ``` :::caution Browser Compatibility `@0gfoundation/0g-compute-ts-sdk` requires polyfills for Node.js built-in modules. **Vite example:** ```bash pnpm add -D vite-plugin-node-polyfills ``` ```javascript // vite.config.js import { nodePolyfills } from 'vite-plugin-node-polyfills'; export default { plugins: [ nodePolyfills({ include: ['crypto', 'stream', 'util', 'buffer', 'process'], globals: { Buffer: true, global: true, process: true } }) ] }; ``` ::: :::warning Manual Fund Management Required in Browser In browser environments, the SDK does **not** auto-fund provider sub-accounts. Auto-funding requires a wallet signature for each transfer, which would trigger unexpected wallet popups (e.g. MetaMask) during active chat sessions — a poor user experience. **For browser dApps, you must manage funds manually:** 1. Deposit to your main account: `await broker.ledger.depositFund(10)` 2. Transfer to the provider sub-account: `await broker.ledger.transferFund(providerAddress, 'inference', amount)` In Node.js environments (server-side), the SDK provides background auto-funding that periodically checks provider sub-account balances and tops up from the ledger as needed. ::: ### Discover Services ```typescript // List all available services const services = await broker.inference.listService(); // Filter by service type const chatbotServices = services.filter(s => s.serviceType === 'chatbot'); const imageServices = services.filter(s => s.serviceType === 'text-to-image'); const speechServices = services.filter(s => s.serviceType === 'speech-to-text'); ``` ### Verify Provider (Optional) All providers listed on the 0G Compute Network have already been verified by the 0G team. This step is optional and intended for users who want to independently verify a provider's TEE attestation. The SDK performs automated checks and provides guidance for manual verification steps. **Automated checks:** - TEE signer address match (contract vs attestation report) - Docker Compose hash verification (calculated vs event log) **Manual steps** (instructions included in output): - Docker image integrity verification via [sigstore](https://search.sigstore.dev/) - Full quote verification using [dstack-verifier](https://github.com/Dstack-TEE/dstack) ```typescript // Verify with real-time step output const result = await broker.inference.verifyService( providerAddress, './reports', // directory to save attestation reports (step) => console.log(step.message) // optional: print each step as it happens ); // Check automated verification results programmatically if (result.signerVerification.allMatch && result.composeVerification.passed) { console.log('Automated checks passed'); } else { console.warn('Automated checks failed — review result for details'); } // Access structured data console.log('Signer match:', result.signerVerification.allMatch); console.log('Compose hash:', result.composeVerification.passed); console.log('Docker images:', result.dockerImages); console.log('Reports saved to:', result.outputDirectory); ``` :::caution Automated checks are not a full verification `verifyService` can only verify signer address and compose hash automatically. To fully verify a provider's TEE environment, you must also follow the manual steps in the output — including running dstack-verifier and checking image integrity via sigstore. ::: ### Account Management For detailed account operations, see [Account](./account-management). :::info Minimum Balance Requirements - **Ledger creation** (`depositFund`): Requires a minimum of **3 0G** for initial deposit - **Provider sub-account**: Each provider requires a minimum locked balance of **1 0G** to serve requests. Transfers below this amount may result in rejected requests. In Node.js environments, the SDK provides background auto-funding that periodically checks provider sub-account balances and tops up from the ledger when insufficient. In browser environments, you must transfer funds manually. ::: ```typescript // Deposit to main account await broker.ledger.depositFund(10); // Node.js: SDK provides background auto-funding that periodically checks // provider sub-account balances and tops up from the ledger when needed. ``` ```typescript // Deposit to main account await broker.ledger.depositFund(10); // Browser: manually transfer funds to provider sub-account (minimum 1 0G). // This also auto-acknowledges the provider's TEE signer on-chain. await broker.ledger.transferFund(providerAddress, 'inference', BigInt(1) * BigInt(10 ** 18)); ``` ### Make Inference Requests ```typescript const messages = [{ role: "user", content: "Hello!" }]; // Get service metadata const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress); // Generate auth headers const headers = await broker.inference.getRequestHeaders( providerAddress ); // Make request const response = await fetch(`${endpoint}/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify({ messages, model }) }); const data = await response.json(); const answer = data.choices[0].message.content; // Optional: verify response integrity via TEE signature (see Response Processing below) const chatID = response.headers.get("ZG-Res-Key") || data.id; if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); } ``` ```typescript const prompt = "A cute baby sea otter"; // Get service metadata const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress); // Generate auth headers const headers = await broker.inference.getRequestHeaders( providerAddress ); // Make request const response = await fetch(`${endpoint}/images/generations`, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify({ model, prompt, n: 1, size: "1024x1024" }) }); const data = await response.json(); const imageUrl = data.data[0].url; // Optional: verify response integrity via TEE signature const chatID = response.headers.get("ZG-Res-Key"); if (chatID) { const isValid = await broker.inference.processResponse(providerAddress, chatID); } ``` ```typescript const formData = new FormData(); formData.append('file', audioFile); // audioFile is a File or Blob formData.append('model', model); formData.append('response_format', 'json'); // Get service metadata const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress); // Generate auth headers const headers = await broker.inference.getRequestHeaders( providerAddress ); // Make request const response = await fetch(`${endpoint}/audio/transcriptions`, { method: "POST", headers: { ...headers }, body: formData }); const data = await response.json(); const transcription = data.text; // Optional: verify response integrity via TEE signature const chatID = response.headers.get("ZG-Res-Key"); if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); } ``` ### Response Processing & Verification :::tip processResponse is optional Use `processResponse` when you want to **verify response integrity** via the provider's TEE signature. Pass the `chatID` from the response header (`ZG-Res-Key`) to enable verification. ::: The `processResponse` method verifies that an inference response came from a genuine TEE environment by checking the provider's signature for the given `chatID`. **Parameters:** - **`providerAddress`**: The address of the provider. - **`chatID`**: Response identifier for TEE verification. Get from `ZG-Res-Key` response header, or fall back to `data.id` for chatbot responses. Returns `null` if omitted (verification skipped). For chatbot services, verify the response using the `chatID` from headers or response body: ```typescript const response = await fetch(`${endpoint}/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify({ messages, model }) }); const data = await response.json(); // Get chatID: prioritize ZG-Res-Key header, fall back to response body let chatID = response.headers.get("ZG-Res-Key") || response.headers.get("zg-res-key"); if (!chatID) { chatID = data.id || data.chatID; } // Verify response integrity via TEE signature if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); console.log("Response valid:", isValid); } ``` For text-to-image services, verify using the `chatID` from response headers: ```typescript const requestBody = { model, prompt: "A cute baby sea otter", size: "1024x1024", n: 1 }; const response = await fetch(`${endpoint}/images/generations`, { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify(requestBody) }); const data = await response.json(); // Get chatID from response headers for verification const chatID = response.headers.get("ZG-Res-Key") || response.headers.get("zg-res-key"); if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); console.log("Response valid:", isValid); } ``` For speech-to-text services, verify using the `chatID` from response headers: ```typescript const formData = new FormData(); formData.append('file', audioFile); formData.append('model', model); const response = await fetch(`${endpoint}/audio/transcriptions`, { method: "POST", headers: { ...headers }, body: formData }); const data = await response.json(); // Get chatID from response headers for verification const chatID = response.headers.get("ZG-Res-Key") || response.headers.get("zg-res-key"); if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); console.log("Response valid:", isValid); } ``` For streaming responses, handle chatID differently based on service type: ```typescript // For chatbot streaming, first check headers then try to get ID from stream let chatID = response.headers.get("ZG-Res-Key") || response.headers.get("zg-res-key"); let streamChatID = null; const decoder = new TextDecoder(); const reader = response.body.getReader(); // Process stream let rawBody = ''; while (true) { const { done, value } = await reader.read(); if (done) break; rawBody += decoder.decode(value, { stream: true }); } // Parse chatID from stream data as fallback for (const line of rawBody.split('\n')) { const trimmed = line.trim(); if (!trimmed || trimmed === 'data: [DONE]') continue; try { const jsonStr = trimmed.startsWith('data:') ? trimmed.slice(5).trim() : trimmed; const message = JSON.parse(jsonStr); if (!streamChatID && (message.id || message.chatID)) { streamChatID = message.id || message.chatID; } } catch {} } // Use chatID from header if available, otherwise from stream data const finalChatID = chatID || streamChatID; if (finalChatID) { const isValid = await broker.inference.processResponse( providerAddress, finalChatID ); console.log("Chatbot streaming response valid:", isValid); } ``` ```typescript // For speech-to-text streaming, get chatID from headers const chatID = response.headers.get("ZG-Res-Key") || response.headers.get("zg-res-key"); if (chatID) { const isValid = await broker.inference.processResponse( providerAddress, chatID ); console.log("Audio streaming response valid:", isValid); } ``` **Key Points:** - **`processResponse` is optional.** Use it when you want to verify response integrity via TEE signature. - Pass the `chatID` parameter to enable verification. Without `chatID`, the method returns `null` (verification skipped). - **chatID retrieval**: Always prioritize `ZG-Res-Key` from response headers. Only use fallback methods when header is not present. - **Chatbot**: First try `ZG-Res-Key` header, then check `data.id` as fallback - **Text-to-Image & Speech-to-Text**: Get chatID from `ZG-Res-Key` response header - **Streaming**: Check headers first, then try to get `id` from stream data as fallback --- ## Understanding Delayed Fee Settlement :::info How Fee Settlement Works 0G Compute Network uses **delayed (batch) settlement** for provider fees. This means: - **Fees are not deducted immediately** after each inference request. Instead, the provider accumulates usage fees and settles them on-chain in batches. - **Your sub-account balance may appear to drop suddenly** when a batch settlement occurs. For example, if you make 10 requests and the provider settles all at once, you'll see a single larger deduction rather than 10 small ones. - **You are only charged for actual usage** — no extra fees are deducted. The total amount settled always matches the sum of your individual request costs. - **This is by design** to reduce on-chain transaction costs and improve efficiency for both users and providers. **What this means in practice:** - After making requests, your provider sub-account balance may temporarily appear higher than your "true" available balance - When settlement occurs, the balance updates to reflect all accumulated fees at once - If you see a sudden balance decrease, check your usage history — the total will match your actual usage This behavior is visible in the Web UI (provider sub-account balances), CLI (`get-account`), and SDK (`getAccount()`). **This applies only to the Direct flow.** The [Router](./router/overview) uses a different billing path with a single unified balance — there are no per-provider sub-accounts and no delayed batch settlement visible to callers. ::: ## Rate Limits :::info Per-User Rate Limits Each provider enforces per-user rate limits to ensure fair resource sharing across all users. The default limits are: - **30 requests per minute** per user (sustained) - **Burst allowance of 5** requests (short spikes allowed) - **5 concurrent requests** per user If you exceed these limits, the provider will return HTTP `429 Too Many Requests`. Wait briefly and retry. These limits are set by individual providers and may vary. ::: ## Troubleshooting ### Common Issues
Error: Too many requests (429) You are sending requests too quickly. Each provider enforces per-user rate limits (default: 30 requests/min, 5 concurrent). - **Wait a few seconds** and retry - **Reduce request frequency** — for batch workloads, add a delay between requests - **Check concurrent requests** — ensure you are not sending more than 5 simultaneous requests
Error: Insufficient balance Your provider sub-account doesn't have enough funds. Each provider requires a minimum locked balance of **1 0G** to serve requests. CLI: #### Deposit to Main Account ```bash 0g-compute-cli deposit --amount 10 ``` #### Transfer to Provider Sub-Account (minimum 1 0G recommended) ```bash 0g-compute-cli transfer-fund --provider --amount 1 ``` SDK: ```typescript // Deposit to main account await broker.ledger.depositFund(10); // Transfer to provider sub-account (minimum 1 0G recommended) await broker.ledger.transferFund(providerAddress, 'inference', BigInt(1) * BigInt(10 ** 18)); ``` > **Note:** In Node.js, the SDK provides background auto-funding that periodically checks sub-account balances and tops up when insufficient. In browser environments, you must transfer funds manually.
Error: Provider not acknowledged You need to acknowledge the provider before using their service. The easiest way is to transfer funds, which auto-acknowledges: CLI: ```bash 0g-compute-cli transfer-fund --provider --amount 1 ``` SDK: ```typescript // transferFund auto-acknowledges the provider's TEE signer await broker.ledger.transferFund(providerAddress, 'inference', BigInt(1) * BigInt(10 ** 18)); ```
Error: No funds in provider sub-account Transfer funds to the specific provider sub-account: ```bash 0g-compute-cli transfer-fund --provider --amount 1 ``` Check your account balance: ```bash 0g-compute-cli get-account ```
Web UI not starting If the web UI fails to start: 1. Check if another service is using port 3090: ```bash 0g-compute-cli ui start-web --port 3091 ``` 2. Ensure the package was installed globally: ```bash pnpm add @0gfoundation/0g-compute-ts-sdk -g ```
## Next Steps - **Manage Accounts** → [Account](./account-management) - **Fine-tune Models** → [Fine-tuning Guide](./fine-tuning) - **Become a Provider** → [Provider Setup](./inference-provider) - **View Examples** → [GitHub](https://github.com/0glabs/0g-compute-ts-starter-kit) --- *Questions? Join our [Discord](https://discord.gg/0glabs) for support.* --- ## 0G Compute Overview Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/overview.md Access affordable GPU computing power for AI workloads through a decentralized marketplace. ## AI Computing Costs Are Crushing Innovation Running AI models today means choosing between: - **Cloud Providers**: $5,000-50,000/month for dedicated GPUs - **API Services**: $0.03+ per request, adding up to thousands monthly - **Building Infrastructure**: Millions in hardware investment **Result**: Only well-funded companies can afford AI at scale. ## Decentralized GPU Marketplace 0G Compute Network connects idle GPU owners with AI developers, creating a marketplace that's: - **90% Cheaper**: Pay only for compute used, no monthly minimums - **Instantly Available**: Access 1000s of GPUs globally - **Verifiable**: Cryptographic proofs ensure computation integrity Think of it as "Uber for GPUs" - matching supply with demand efficiently. ## Architecture Overview ![0G Compute Network Architecture](https://docs.0g.ai/assets/images/architecture-321f88478d71dcdff10cf2baf5b12551.png) The network consists of: 1. **Smart Contracts**: Handle payments and verification 2. **Provider Network**: GPU owners running compute services 3. **Client SDKs**: Easy integration for developers 4. **Verification Layer**: Ensures computation integrity ## Key Components ### 🤖 Supported Services | Service Type | What It Does | Status | |--------------|--------------|--------| | **Inference** | Run pre-trained models (LLMs) | ✅ Live | | **Fine-tuning** | Fine-tune models with your data | ✅ Live | | **Training** | Train models from scratch | 🔜 Coming | ### 🔐 Trust & Verification **Verifiable Computation**: Proof that work was done correctly - TEE (Trusted Execution Environment) for secure processing - Cryptographic signatures on all results - Can't fake or manipulate outputs
What makes it trustworthy? **Smart Contract Escrow**: Funds held until service delivered - Like eBay's payment protection - Automatic settlement on completion - No payment disputes
## Quick Start Paths ### 👨‍💻 "I want to use AI services" Two integration paths — pick one: **[Compute Router](./router/overview)** *(recommended for most apps)* — a single OpenAI-compatible endpoint with one unified balance, automatic provider failover, and an API key. Ideal for server-side apps, agents, and prototypes. 1. Get an API key at [pc.0g.ai](https://pc.0g.ai) 2. Deposit 0G tokens 3. Point your OpenAI SDK at `https://router-api.0g.ai/v1` **[Direct](./direct)** — connect to individual providers via the `@0gfoundation/0g-compute-ts-sdk` SDK, manage per-provider sub-accounts, sign requests with your wallet. Use this for browser dApps with wallet signing, on-chain control, or when you need **fine-tuning** (Router is inference-only). 1. [Install SDK](./inference) and pick a provider 2. [Fund your account](./account-management) — shared across inference and fine-tuning 3. Run [Inference](./inference) or [Fine-tuning](./fine-tuning) Deeper comparison: [Router vs Direct](./router/comparison). ### 🖥️ "I have GPUs to monetize" Turn idle hardware into revenue: 1. Check [hardware requirements](./inference-provider#prerequisites) 2. [Set up provider software](./inference-provider#launch-provider-broker) ### 🎯 "I need to fine-tune AI models" Fine-tune models with your data: 1. [Install CLI tools](./fine-tuning#install-cli) 2. [Prepare your dataset](./fine-tuning#prepare-your-data) 3. [Start fine-tuning](./fine-tuning#create-task) ## Frequently Asked Questions
How much can I save compared to OpenAI? Typically 90%+ savings: - OpenAI GPT-4: ~$0.03 per 1K tokens - 0G Compute: ~$0.003 per 1K tokens - Bulk usage: Even greater discounts
Is my data secure? - Every provider runs inside a TEE (Trusted Execution Environment) that isolates the serving process from external access to your inference traffic. - Provider responses are cryptographically signed by the TEE's private key, so you can verify the exact model that ran. - The Router stores only billing metadata (token counts, model, provider, timestamp) — not request or response bodies.
How fast is it compared to centralized services? Observed latency varies by model, provider load, and your distance to the provider. For chatbot workloads it is typically in the same range as centralized API services; check the provider list at [pc.0g.ai](https://pc.0g.ai) for live health and latency data per provider.
--- *0G Compute Network: Democratizing AI computing for everyone.* --- ## Deposits & Billing Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/account/deposits.md The Router charges on-chain, per token, from a single balance that covers every model, every provider, every service type. You deposit once; you're done until the balance runs out. :::note Separate from Direct sub-accounts The balance you use with the Router is distinct from the per-provider sub-accounts used by the [Direct](../../direct) flow / [compute-marketplace.0g.ai](https://compute-marketplace.0g.ai). Funds in one do not back calls in the other. See [Router vs Advanced Mode](../comparison#pc0gai-router-vs-advanced-mode) if you've been using the old flow. ::: ## Deposit You deposit to the **0G Payment Layer** — a shared balance contract used across all 0G products, not just the Router. Deposit once, and any 0G product you use (Router included) draws from the same pool. The easiest way is **[pc.0g.ai](https://pc.0g.ai) → Dashboard → Deposit**. It's a normal on-chain transaction signed by your wallet; funds are usable within a few seconds of confirmation. Payment Layer contract addresses: | Network | Address | |---|---| | Mainnet | `0xA3b15Bd2aD18BFB6b5f92D8AA9F444Dd59d1cE32` | | Testnet | `0x0AD9690e0b34aB2d493DE02cDF149ee34f6C9939` | ## How Costs Are Calculated ```text total_cost = (input_tokens × prompt_price) + (output_tokens × completion_price) ``` - Prices are declared per model and quoted in **neuron per token** (1e18 neuron = 1 0G) - `input_tokens` includes the full conversation context you send (system prompt + prior messages + current user message) - Image and audio endpoints price per request or per second depending on the model — see the catalog Get current prices from [`GET /v1/models`](../models) or the model card on [pc.0g.ai](https://pc.0g.ai). The Router does not add markup — what the provider charges is what you pay. :::note Cached-token pricing Tiered pricing for cached prompt tokens is on the roadmap — a future release will report cached and fresh input tokens separately and bill them at distinct rates. ::: ## Check Your Balance `/v1/account/*` endpoints require a **management key** with the `account:read` scope (see [Authentication](../authentication)) — `sk-` keys return `403 insufficient_scope`. ```bash curl https://router-api.0g.ai/v1/account/balance \ -H "Authorization: Bearer mk-YOUR_MANAGEMENT_KEY" ``` ```json { "address": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", "deposit_balance": "2000000000000000000", "total_balance": "2000000000000000000" } ``` Values are in **neuron**. `total_balance` is what is available to spend right now. It may lag your Payment Layer balance slightly because the Router pulls from the Payment Layer in batches (see below). When `total_balance` hits zero and the Payment Layer is also empty, the next inference request returns `402 insufficient_balance`. ## Check Your Usage Aggregate stats: ```bash curl "https://router-api.0g.ai/v1/account/usage/stats?start_date=2026-04-01" \ -H "Authorization: Bearer mk-YOUR_MANAGEMENT_KEY" ``` Returns total requests, total tokens (prompt/completion split), and total cost for the window. Per-request history: ```bash curl "https://router-api.0g.ai/v1/account/usage/history?limit=20&offset=0" \ -H "Authorization: Bearer mk-YOUR_MANAGEMENT_KEY" ``` Returns a paginated list of individual requests with model, provider address, token counts, and cost. Both endpoints also accept `api_key_id`, `source`, `start_date`, and `end_date` filters. ## Related - [**Authentication**](../authentication) — how to create, rotate, and revoke the API keys billed against this balance - [**Rate Limits**](../rate-limits) - [**Errors**](../errors) — especially `402 insufficient_balance` --- ## How funds reach the Router (advanced) You don't need to know this to use the Router, but if you're curious about the on-chain flow: 1. You deposit to the **Payment Layer** contract. The deposit belongs to your wallet address. 2. The Router runs a background **PaymentWorker** that watches for users whose Router-side balance is below a threshold and who have an active usage pattern. For those users, the worker asks the Payment Layer to release a small tranche of your balance into the Router's internal payment contract. 3. The Router then debits that internal contract as you consume tokens, and periodically settles the consumed amount to individual providers on-chain. This two-step design (Payment Layer → Router) means the Payment Layer balance is shared across all 0G products, and the Router only holds what it needs for your near-term usage. From your side, the only thing you interact with is the Payment Layer deposit — everything else is automatic. --- ## Authentication Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/authentication.md :::caution Breaking change (existing users) `sk-` keys no longer have access to `/v1/account/*` (balance, usage, history). Issue an `mk-` key with the `account:read` scope and update your dashboard / billing code. ::: The Router accepts two kinds of credentials, distinguished by prefix: | Key type | Prefix | What it's for | | ------------------ | ------ | --------------------------------------------------------------------------------------------- | | **API key** | `sk-` | Call inference endpoints (`/v1/chat/completions`, etc.). Billed against your deposit. | | **Management key** | `mk-` | Administer your account: list / create / revoke API keys, read balance and usage. Not billed. | Ship `sk-` keys to the runtime that actually calls models; use `mk-` keys for dashboards, audit integrations, and CI that needs to provision or rotate API keys. Both kinds go in the `Authorization` header — same shape: ```text Authorization: Bearer sk-YOUR_API_KEY ``` ```text Authorization: Bearer mk-YOUR_MANAGEMENT_KEY ``` No OAuth flow, no wallet signature per request, no session tokens. For the full request / response shape of every endpoint, see the **[Router API reference](https://0gfoundation.github.io/0g-router/)**. ## Permission matrix One table covers what each credential can do and what scope it needs. `✅` = allowed, `❌` = `403 insufficient_scope`. | Scenario | Endpoint | `sk-` API key | `mk-` Management key | | ------------------------------ | ----------------------------------- | :-----------: | :--------------------- | | Run inference | `POST /v1/chat/completions` (etc.) | ✅ | ❌ | | Read balance / usage / history | `GET /v1/account/*` | ❌ | ✅ `account:read` | | List API keys | `GET /v1/api-keys` | ❌ | ✅ `keys:read` | | Create API key | `POST /v1/api-keys` | ❌ | ✅ `keys:create` | | Edit / revoke API key | `PATCH`/`DELETE /v1/api-keys/:id` | ❌ | ✅ `keys:manage` | | Manage management keys | `ANY /v1/management-keys/*` | ❌ | ❌ — wallet JWT only | Two guardrails worth calling out: - **Management keys cannot manage other management keys.** `ANY /v1/management-keys/*` requires the wallet JWT (sign-in session). A leaked `mk-` cannot mint replacements for itself. - **`keys:manage` and `keys:create` are deliberately split.** A read-only audit integration that should be able to revoke a compromised key but **not** issue replacements gets `{keys:read, keys:manage}` and is locked out of issuance. ## API keys (`sk-`) Created at **[pc.0g.ai](https://pc.0g.ai) → Dashboard → API Keys**. From there you can: - **Create** a new key — label it so you can tell keys apart (e.g. `staging`, `agent-bot`, `my-laptop`). The full secret is shown **once** on creation; copy it immediately. The dashboard only stores a hash. - **List** existing keys with their labels, created-at, and last-used timestamps. - **Revoke** any key instantly — in-flight requests using a revoked key return `401 api_key_revoked` on their next call. ## Management keys (`mk-`) Created at **[pc.0g.ai → Settings → Management Keys](https://pc.0g.ai)**. Each key carries an explicit allowlist of scopes — see the matrix above. When creating a key, pick a preset or check scopes individually: - **Read-only** — `account:read`, `keys:read`. Dashboards, monitoring. - **Key Manager** — `keys:read`, `keys:manage`. Rotate / revoke existing keys, no issuance. - **Full Admin** — all four scopes. CI that provisions per-deploy API keys. - **Custom** — pick any subset. **Audit fields.** Every successful request with an `mk-` key updates `last_used_at` and `last_source_ip` on the key. Writes are coalesced to at most one per key per 60 seconds. IPv4-mapped IPv6 addresses (`::ffff:1.2.3.4`) are normalized to dotted-quad so a dual-stack vs IPv4-only listener doesn't make one client look like two. (`sk-` keys don't record these — their audit signal is usage / billing.) **Expiration.** Management keys do not expire. Rotate on a schedule by issuing a replacement and revoking the old key. ## Best practices - **One key per deployment.** Separate staging / production / per-service keys so you can revoke one without touching the others. - **Least privilege for `mk-`.** Don't grant `keys:create` to an integration that only needs to read. The preset selector is there for a reason. - **Rotate on suspicion.** If a key might have leaked, revoke it and issue a new one — takes seconds. - **Watch `last_used_at` on management keys.** A key that hasn't been used in months is a key you can probably revoke. :::caution Never ship keys to browsers Whoever has your `sk-` key can spend the 0G tokens you deposited; whoever has your `mk-` key can issue more `sk-` keys. Keep both server-side and proxy client requests through your own backend. ::: --- ## Claude Code Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/clients/claude-code.md [Claude Code](https://code.claude.com/docs) reaches the Router over the Anthropic Messages API, so it needs configuration only — no plugin, no proxy. ## Configure Create `~/.claude/settings.json` (Windows: `C:\Users\\.claude\settings.json`) and replace `YOUR_API_KEY` with a Router [API key](../authentication): ```json { "env": { "ANTHROPIC_BASE_URL": "https://router-api.0g.ai", "ANTHROPIC_AUTH_TOKEN": "YOUR_API_KEY", "ANTHROPIC_API_KEY": "", "ANTHROPIC_MODEL": "glm-5.2", "ANTHROPIC_DEFAULT_FABLE_MODEL": "glm-5.2", "ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-5.2", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "0gm-1.0-35b-a3b", "CLAUDE_CODE_MAX_CONTEXT_TOKENS": "983616" }, "modelOverrides": { "claude-sonnet-5": "0gm-1.0-35b-a3b" } } ``` Then run: ```bash claude --permission-mode auto ``` :::tip Private mode Both models above are TEE-backed (`"verifiability": "TeeML"`). To guarantee every Claude Code request runs inside an enclave, create the key with trust mode **Private** in Dashboard → API Keys — that key routes only to TeeML providers regardless of what the client sends. See [Privacy & ZDR](../privacy#enabling-privacy-mode). ::: ## Notes - **`modelOverrides`** sets the model behind auto mode's permission gate, which runs before every non-read-only action. Use it rather than `ANTHROPIC_DEFAULT_SONNET_MODEL`: that one replaces the slot, leaving Claude Code unable to recognize the model, so it stops disabling reasoning and a yes/no check turns into a full reasoning pass. - **`ANTHROPIC_DEFAULT_HAIKU_MODEL`** covers background work — session names for `claude --resume`, status for commands like `/usage`. - **`CLAUDE_CODE_MAX_CONTEXT_TOKENS`** is the main model's real context window. Without it Claude Code assumes 200 K and compacts at a fifth of `glm-5.2`'s 1 M. - **`--permission-mode auto`** is required per session, or set `{"permissions": {"defaultMode": "auto"}}` in `~/.claude/settings.json`. With an API key, sessions otherwise start in Manual mode. - Everything under `env` also works as shell exports; `modelOverrides` does not. ## Models Claude Code needs a model that serves the Anthropic Messages API: ```bash curl -s https://router-api.0g.ai/v1/models \ | jq -r '.data[] | select(.supported_formats | index("anthropic")) | .id' ``` Any of those work in any slot. See [Models](../models) for pricing and context windows. --- ## Router vs Direct Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/comparison.md The 0G Compute Network exposes the same underlying providers through two integration paths. This page helps you choose. ## At a Glance | | **Router** | **[Direct](../direct)** | | -------------------------- | ----------------------------------------- | ----------------------------------------- | | **Where the request signs from** | Router API key (server-side) | User's wallet (client or server) | | **API shape** | OpenAI / Anthropic compatible | 0G SDK calls | | **Provider selection** | Automatic with failover | Manual — you choose and fund each | | **Billing** | Single unified on-chain balance | Per-provider sub-accounts | | **Browser-safe** | Only via your backend (API keys are secret) | Yes — user's wallet signs each request | | **Integration effort** | Change `base_url` + API key | Install SDK, manage keys, handle signing | | **On-chain transparency** | Settled periodically in batches | Every call settles against a sub-account | | **Typical user** | Backend service, agent framework, prototype | Wallet-connected dApp, on-chain agent | ## Pick the Router When… - You're building a **server-side app** — an agent, a backend, a CLI, an automation. - You want to **reuse existing OpenAI/Anthropic code** without rewriting for a new SDK. - You don't want to manage per-provider funding or provider discovery yourself. - You want one balance covering every model, every service. - You're prototyping and want the shortest path from signup to first request. ## Pick Direct When… - You're building a **browser dApp** where the end user's wallet signs requests — API keys should never ship to browsers. - You need **direct smart-contract interaction** — reading provider state, on-chain settlement receipts, custom escrow logic. - You want to **choose and fund specific providers** with tight control, not a gateway's routing policy. - You're writing an on-chain agent or a contract that calls providers directly. ## Can I Use Both? Yes. The balances are separate (Router balance vs per-provider sub-accounts), but nothing prevents a single project from using the Router for backend workloads and Direct for a browser-wallet dApp. ## pc.0g.ai: Router vs Advanced Mode The [pc.0g.ai](https://pc.0g.ai) Web UI exposes **both** integration paths through a mode toggle in the top-right: | Mode in UI | What it is | Where funds live | | -------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | **Router** (default) | This documentation. Unified API gateway with a single balance. | 0G **Payment Layer** — shared contract across all 0G products, single pool across all models/providers | | **Advanced** | The classic [Direct](../direct) flow, embedded in the new UI | Per-provider sub-accounts — same as [compute-marketplace.0g.ai](https://compute-marketplace.0g.ai) | **The two balance pools are independent.** A Router deposit does not fund your provider sub-accounts, and sub-account balances do not back Router API calls. They live in different contracts. ### For existing compute-marketplace.0g.ai users If you've been using [compute-marketplace.0g.ai/wallet](https://compute-marketplace.0g.ai/wallet) and your funds don't appear in the default Router view on pc.0g.ai — that's expected. Click **Advanced** (top-right) to switch to the sub-account view where your existing balances are shown. Nothing has been lost; you're looking at the wrong pool. If you want to consolidate onto the Router, withdraw from the per-provider sub-accounts in Advanced mode, then deposit the tokens into the Router balance from the default view. ## See Also - **[Router Overview](./overview)** - **[Direct](../direct)** — SDK-based path (inference, fine-tuning, and account management) --- ## Errors Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/errors.md Errors follow a consistent OpenAI-compatible shape. The response also includes `request_id` at the top level when available — quote it when reporting issues. ```json { "error": { "message": "Insufficient balance to process request", "type": "payment_error", "code": "insufficient_balance" }, "request_id": "req_abc123" } ``` ## HTTP Status Codes | Status | Meaning | | ------ | ------------------------------------------------------------------------------- | | `400` | Bad request — invalid model, malformed body, unsupported feature for model | | `401` | Missing or invalid authentication | | `402` | Insufficient balance — [deposit more](./account/deposits) | | `403` | The API key does not have permission to perform this action | | `404` | Resource not found | | `429` | Rate limited — check `Retry-After` header, see [Rate Limits](./rate-limits) | | `502` | Provider returned an error (failover exhausted) | | `503` | No healthy providers available for the requested model | ## Error Types and Codes `error.type` groups errors into a small set of buckets; `error.code` identifies the specific cause. | `type` | `code` (examples) | When it happens | | ----------------------- | ------------------------------------------------------------ | ---------------------------------------------------- | | `invalid_request_error` | `invalid_body`, `missing_authorization`, `invalid_api_key`, `api_key_revoked`, `invalid_provider_header`, `invalid_max_price_usd`, `no_provider_within_max_price`, `pinned_provider_exceeds_max_price` | 400, 401 — request, auth, or routing headers are wrong (incl. malformed `X-0G-Provider-*` values and unsatisfiable price ceilings) | | `payment_error` | `insufficient_balance` | 402 — not enough 0G deposited | | `permission_error` | `access_denied` | 403 — the key is not allowed to perform this action | | `not_found_error` | `api_key_not_found` | 404 — resource doesn't exist | | `rate_limit_error` | `rate_limit_exceeded` | 429 — see [Rate Limits](./rate-limits) | | `server_error` | `no_available_provider`, `provider_error`, `internal_error` | 502, 503, 500 — backend problem | ## Retrying - `429` — honor `Retry-After`, then retry - `502` (`provider_error`) — the Router already tried every healthy provider; retrying may help if one just came back online - `503` (`no_available_provider`) — unlikely to resolve in seconds; consider a different model or waiting Do **not** retry `400`, `401`, `402`, or `403` without changing your request — they won't succeed. ## Related - [**Rate Limits**](./rate-limits) - [**Deposits & Billing**](./account/deposits) --- ## Router FAQ Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/faq.md ## I deposited on compute-marketplace.0g.ai but don't see my balance on pc.0g.ai — where did my 0G go? Nowhere. Those funds live in **per-provider sub-accounts** under the [Direct](../direct) flow, and pc.0g.ai defaults to showing the **Router** balance, which is a different on-chain pool. Click the **Advanced** toggle in the top-right of pc.0g.ai. Advanced mode is the same Direct flow you've been using, just embedded in the new UI — your sub-account balances appear there. See [Router vs Advanced Mode](./comparison#pc0gai-router-vs-advanced-mode) for a side-by-side breakdown of the two systems. ## Do I need a wallet to use the Router? Yes. The Router bills on-chain, so you need a wallet to deposit 0G tokens and create API keys. [pc.0g.ai](https://pc.0g.ai) supports MetaMask and WalletConnect for direct wallet connect, plus social sign-in via Privy (Google, X/Twitter, Discord, TikTok) which provisions an embedded wallet for you. Once you have an API key, your application code doesn't touch the wallet again — it just sends `Authorization: Bearer sk-…`. ## What is TEE and why does it matter? A **Trusted Execution Environment** is a hardware-isolated region where code runs with cryptographic attestation of exactly what was executed. Every provider on the 0G Compute Network runs inside a TEE and attests to the model they serve. This is what makes "decentralized inference" meaningful: you can verify, out-of-band, that the model you asked for is the model that ran — not a silently-swapped cheaper model. ## What token do I pay in? **0G tokens**, native to the 0G chain. Deposit once to the Router payment contract; the Router handles conversions and provider payouts. ## Is the Router really OpenAI-compatible? Yes. Any OpenAI client library — `openai-python`, `openai-node`, LangChain, LlamaIndex, Vercel AI SDK, etc. — works by changing `base_url` to `https://router-api.0g.ai/v1` and `api_key` to your Router key. ## How is pricing set? Each provider declares prices per model (input tokens, output tokens). The Router publishes these in `/v1/models`. When you route with `sort: "price"`, the cheapest provider wins; otherwise failover picks a healthy provider regardless of price. There is no Router markup on top of provider prices — what you see in the catalog is what you pay. ## What happens if no providers are available? If every provider for your chosen model is unhealthy, you get `503 no_providers_available`. The Router does **not** fall back to a different model — picking a model is your decision. Choose a different model yourself, or wait and retry. ## Does the Router store my prompts? No. The Router persists only billing metadata (token counts, model, provider, timestamp). Request and response bodies are not stored. If you need content audit logs, log them yourself on the caller side. ## Can I run my own provider? Yes. See the [Inference Provider Setup](../inference-provider) guide. Once you're registered and healthy, the Router will start routing traffic to you alongside existing providers. ## Where do I get help? - [**Discord**](https://discord.gg/0glabs) — the `#compute` channel - [**GitHub Issues**](https://github.com/0gfoundation) for bug reports --- ## Audio Transcription Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/audio.md **`POST /v1/audio/transcriptions`** Fully compatible with the [OpenAI Audio Transcription API](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create). Send audio as `multipart/form-data`; the OpenAI SDK does this automatically. ```bash curl https://router-api.0g.ai/v1/audio/transcriptions \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -F "file=@recording.mp3" \ -F "model=openai/whisper-large-v3" \ -F "response_format=json" ``` ```python from openai import OpenAI client = OpenAI( base_url="https://router-api.0g.ai/v1", api_key="sk-YOUR_API_KEY", ) with open("recording.mp3", "rb") as f: result = client.audio.transcriptions.create( model="openai/whisper-large-v3", file=f, response_format="json", ) print(result.text) ``` ## Fields | Field | Description | | ----------------- | --------------------------------------------------------------- | | `model` | Audio model ID from [`/v1/models`](../models) | | `file` | Audio file (multipart form) | | `response_format` | `json`, `text`, `srt`, `verbose_json`, `vtt` | | `language` | ISO-639-1 code, e.g. `"en"` — optional, improves accuracy | | `prompt` | Optional text to guide style and vocabulary | | `temperature` | Sampling temperature (0 = deterministic) | ## Response ```json { "text": "Hello, this is a transcription of the audio file." } ``` ## 0G Router Extensions Because this endpoint uses `multipart/form-data` instead of a JSON body, Router extensions are passed out-of-band — as a query parameter for `verify_tee`, and as `X-0G-Provider-*` request headers for provider routing. **TEE verification** — pass `verify_tee` as a query parameter: ```text ?verify_tee=true ``` See [Verifiable Execution](./verifiable-execution) for what `tee_verified` means in the response. **Provider routing** — pass `X-0G-Provider-*` headers, the same surface as JSON endpoints: ```bash curl https://router-api.0g.ai/v1/audio/transcriptions \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Sort: latency" \ -F "file=@recording.mp3" \ -F "model=openai/whisper-large-v3" ``` See [Provider Routing](../routing) for the full header reference. ## Related - [**Models**](../models) — list available audio models - [**Verifiable Execution**](./verifiable-execution) --- ## Chat Completions Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/chat-completions.md **`POST /v1/chat/completions`** Fully compatible with the [OpenAI Chat Completions API](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create). Supports streaming, tool calling, JSON mode, and reasoning-token models. ## Request ```json { "model": "glm-5.2", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Explain quantum computing in simple terms."} ], "temperature": 0.7, "max_tokens": 1024, "stream": true } ``` All standard OpenAI fields are accepted — `temperature`, `top_p`, `n`, `stop`, `presence_penalty`, `frequency_penalty`, `logit_bias`, `user`, `response_format`, and so on. ### 0G Router Extensions Optional top-level fields. Stripped before the request is forwarded to the provider, so they never conflict with the OpenAI schema. | Field | Type | Description | | ------------ | ------- | ------------------------------------------------------------------------------------ | | `provider` | object | **Deprecated** — prefer `X-0G-Provider-*` request headers. See [Routing](../routing) | | `verify_tee` | boolean | Ask the Router to synchronously verify the provider's TEE signature — see [Verifiable Execution](./verifiable-execution) | ## Streaming Set `"stream": true` to receive Server-Sent Events in the OpenAI SSE format. Any OpenAI client library that handles streaming will work unchanged. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Write a haiku about decentralization"}], "stream": true }' ``` :::tip Reasoning models Some models (e.g. GLM-5) emit a `reasoning_content` field in streaming deltas before the final `content`. Client libraries that know about reasoning tokens will surface both separately. ::: ## Tool Calling Models that advertise tool-calling capability accept the standard OpenAI `tools` / `tool_choice` fields. ```json { "model": "glm-5.2", "messages": [ {"role": "user", "content": "What's the weather in Tokyo?"} ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get current weather for a city", "parameters": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } } ] } ``` :::caution Check model capabilities **Not every model supports tool calling.** Before sending a request with `tools`, verify the model's capability flags in the [catalog](../models) or on [pc.0g.ai](https://pc.0g.ai). Sending `tools` to a model that doesn't support it returns `400 Bad Request`. ::: The response shape (`tool_calls` in the assistant message, `tool` role for results) matches OpenAI exactly. ## JSON Mode For models that support structured output: ```json { "model": "glm-5.2", "messages": [ {"role": "system", "content": "Respond with JSON only."}, {"role": "user", "content": "List three colors and their hex codes."} ], "response_format": {"type": "json_object"} } ``` As with tool calling, check capability flags before using. ## Response shape Responses are OpenAI-compatible (`choices[]`, `usage`, `model`, `id`, `object`, `created`). The Router adds two Router-specific additions on top: ### `x_0g_trace` (always present) Every Router response carries an `x_0g_trace` object with metadata about the request's execution: ```json "x_0g_trace": { "request_id": "0852f405-6c56-40c2-a800-e6fd70785065", "provider": "0xd9966e13a6026Fcca4b13E7ff95c94DE268C471C", "billing": { "input_cost": "19000000000000", "output_cost": "1916800000000000", "total_cost": "1935800000000000" } } ``` | Field | Description | | --- | --- | | `request_id` | Unique ID for this request. Quote it in any support ticket or bug report. | | `provider` | On-chain address of the provider that served the request | | `billing.input_cost` / `output_cost` / `total_cost` | Exact cost in **neuron** for this specific request | | `tee_verified` | Present only when `verify_tee: true` was set — see [Verifiable Execution](./verifiable-execution) | This means you don't need to compute costs yourself — the Router tells you exactly what was charged. Handy for per-request logging and client-side budget tracking. ### `reasoning_content` (thinking models) For models with thinking support (e.g. `glm-5.2`), the Router returns the reasoning trace alongside the final answer. It appears in two equivalent places: ```json "choices": [{ "message": { "role": "assistant", "content": "{ \"colors\": [ ... ] }", "reasoning_content": "The user wants a JSON response...", "provider_specific_fields": { "reasoning_content": "The user wants a JSON response..." } } }] ``` Both fields contain the same text; most OpenAI SDKs surface `reasoning_content` directly on the message. You can ignore it for production output, log it for debugging, or display it to the user as "thinking". :::tip Disable thinking for GLM-5 Thinking is on by default for GLM-5. If you don't want it (saves tokens and latency), pass `chat_template_kwargs: {"enable_thinking": false}` in the request body — GLM-5 advertises this in its `supported_parameters`. ::: ## Related - [**Routing**](../routing) — choose your provider - [**Errors**](../errors) — response codes and error shapes --- ## Image Generation Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/image-generation.md The Router exposes two paths for image generation: - **Synchronous** — drop-in OpenAI-compatible endpoint (`POST /v1/images/generations`). Returns the image in the same request. Best when you're using the OpenAI SDK directly or have short/fast models. - **Asynchronous (recommended for production)** — submit a job and poll (`POST /v1/async/images/generations` + `GET /v1/async/jobs/{jobId}`). Avoids long-held HTTP connections. Best for slow models, batch workloads, serverless, or browser reliability. Both paths accept the same request shape and produce the same final output. :::caution `response_format: "b64_json"` is currently required Always send `"response_format": "b64_json"`. Base64 is the only format supported end-to-end right now; URL-based responses will be enabled in a future release. This applies to **both** sync and async paths. ::: ## Synchronous — OpenAI-compatible **`POST /v1/images/generations`** Fully compatible with the [OpenAI Images API](https://developers.openai.com/api/reference/resources/images/methods/generate) — any OpenAI client library works unchanged once you switch the base URL. ```bash curl https://router-api.0g.ai/v1/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "z-image", "prompt": "A serene mountain landscape at sunset", "n": 1, "size": "1024x1024", "response_format": "b64_json" }' ``` ```python from openai import OpenAI client = OpenAI( base_url="https://router-api.0g.ai/v1", api_key="sk-YOUR_API_KEY", ) result = client.images.generate( model="z-image", prompt="A serene mountain landscape at sunset", n=1, size="1024x1024", response_format="b64_json", ) print(result.data[0].b64_json[:80], "...") ``` Returns the standard OpenAI image response: a `data` array with `b64_json` entries. Decode on the client to render. ### Request fields | Field | Required | Description | | ----------------- | -------- | -------------------------------------------------------------- | | `model` | ✓ | Image model ID from [`/v1/models`](../models) | | `prompt` | ✓ | Text description of the desired image | | `response_format` | ✓ | Must be `"b64_json"` today; `"url"` support is planned | | `n` | | Number of images to generate | | `size` | | e.g. `"1024x1024"` — check the model for supported sizes | ## Asynchronous (recommended for production) Image generation can take tens of seconds. Holding an HTTP connection open that long is fragile — short-timeout clients, browsers, and serverless functions will drop it. The async path solves this: submit once, poll until ready. ### 1. Submit a job **`POST /v1/async/images/generations`** — same body as the synchronous endpoint. ```bash curl https://router-api.0g.ai/v1/async/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "z-image", "prompt": "A serene mountain landscape at sunset", "n": 1, "size": "1024x1024", "response_format": "b64_json" }' ``` The Router responds immediately with a job handle: ```json { "jobId": "5b595c31955d4be2923f5070705cced4", "status": "pending", "provider_address": "0xE29a72..." } ``` `provider_address` identifies which provider is handling your job. You'll pass it back when polling — async jobs are pinned to their provider. ### 2. Poll for the result **`GET /v1/async/jobs/{jobId}?provider_address={addr}`** ```bash curl "https://router-api.0g.ai/v1/async/jobs/5b595c31955d4be2923f5070705cced4?provider_address=0xE29a72..." \ -H "Authorization: Bearer sk-YOUR_API_KEY" ``` While the job is running, `status` is `"pending"` (or `"running"`). When finished, `status: "completed"` appears with the result payload and an injected `x_0g_trace`: ```json { "status": "completed", "createdAt": "2026-04-24T09:44:57.804Z", "data": { "created": 1777023898, "data": [ { "b64_json": "iVBORw0KGgoAAAANSUhEUg..." } ] }, "x_0g_trace": { "request_id": "...", "provider": "0x...", "billing": { "input_cost": "...", "output_cost": "...", "total_cost": "..." } } } ``` The image array lives at `data.data[]` — the outer `data` is a wrapper object the provider returns around the OpenAI-style result, not the OpenAI array itself. :::tip Use the `Retry-After` header for polling cadence Both submit and poll responses forward a `Retry-After` header (in seconds) when the provider sends one — use that value to decide when to poll again, since it reflects the provider's current queue. Fall back to a fixed 2–3 second interval only if the header is missing. ::: ## 0G Router Extensions The same optional top-level fields as chat completions, stripped before forwarding to the provider (applies to both sync and async paths): | Field | Type | Description | | ------------ | ------- | ------------------------------------------------------------------------------------ | | `provider` | object | **Deprecated** — prefer `X-0G-Provider-*` request headers. See [Routing](../routing) | | `verify_tee` | boolean | Ask the Router to synchronously verify the provider's TEE signature — see [Verifiable Execution](./verifiable-execution) | ## Billing Image generation is charged per image at rates declared by the model (see `pricing.image` in the [catalog](../models)). Billing is tied to the provider's execution, not to your client holding the connection: - **Submission starts the clock.** Once the provider accepts the job, generation begins. - **Abandoning a poll does not cancel the job.** If you close the HTTP connection, stop polling, or kill your process after submitting, the provider still runs the job to completion and you are still billed. ## Related - [**Models**](../models) — browse available image models and sizes - [**Routing**](../routing) - [**Verifiable Execution**](./verifiable-execution) --- ## Verifiable Execution Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/features/verifiable-execution.md Every 0G Compute provider runs inside a **Trusted Execution Environment (TEE)** and cryptographically signs its responses. The Router can verify that signature synchronously on your behalf and report the result back in the response metadata. ## Opt in with `verify_tee` Add `verify_tee: true` to any inference request, and the Router will verify the provider's TEE signature before returning the response. The verification result appears in the response trace. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}], "verify_tee": true }' ``` For endpoints that use `multipart/form-data` (like `/v1/audio/transcriptions` or image edits), pass `verify_tee` as a query parameter instead: ```bash curl "https://router-api.0g.ai/v1/audio/transcriptions?verify_tee=true" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -F "file=@recording.mp3" \ -F "model=openai/whisper-large-v3" ``` `verify_tee` is a 0G Router extension — it's stripped from the request before being forwarded to the provider, so it doesn't interfere with the OpenAI-compatible schema. ## Reading the result When `verify_tee` is set, the Router adds a `tee_verified` field to the response's `x_0g_trace` metadata block (which is present on every Router response — see [Response shape](./chat-completions#response-shape)): ```json "x_0g_trace": { "request_id": "0852f405-6c56-40c2-a800-e6fd70785065", "provider": "0xd9966e13a6026Fcca4b13E7ff95c94DE268C471C", "billing": { "input_cost": "...", "output_cost": "...", "total_cost": "..." }, "tee_verified": true } ``` | `tee_verified` | Meaning | | --- | --- | | `true` | The provider's TEE signature was validated successfully | | `false` | A signature was present but did not verify — treat the response as untrusted | | `null` / absent | Verification was not requested for this response | ## When to use it - **Most chat-like applications** don't need per-request verification — the provider is already inside a TEE, and the network tolerates a small rate of signed-but-unverified responses. - **Audit logs, high-trust pipelines, and research workloads** benefit from setting `verify_tee: true` so that every response carries a validated attestation flag alongside it. - The pc.0g.ai UI enables `verify_tee` by default for playground requests; feel free to mirror that behaviour in your own clients. ## Trust model `verify_tee: true` asks the **Router** to fetch the provider's TEE signature, look up the signer address on-chain, and verify the signature on your behalf. The Router returns a single boolean (`tee_verified`) summarising that check. In other words, `tee_verified: true` in the response says *"the Router says it verified the signature."* It does **not** carry the raw signature back to you — you still have to trust the Router to have done the check honestly. If that level of trust is acceptable for your application, stop here: set `verify_tee: true` and read the flag. If you need an independent guarantee, **all the inputs the Router uses are public**, and you can reproduce the verification yourself. See the next section. ## Independent verification (advanced) You don't have to trust the Router's `tee_verified` flag — the underlying inputs are all public, and the `@0gfoundation/0g-compute-ts-sdk` SDK ships a one-shot helper that does the whole verification for you. ### With the SDK (recommended) The `chatID` required for verification comes from the **`ZG-Res-Key` response header** (the `id` field in the JSON body is a fallback when the header is absent). That means you need access to the raw HTTP response headers — `fetch` works directly; for OpenAI SDKs use their "raw response" / "with-response" helper. ```typescript import { ethers } from "ethers"; import { createZGComputeNetworkBroker } from "@0gfoundation/0g-compute-ts-sdk"; // Any wallet works — processResponse only reads the chain and calls the provider's public signature endpoint. const rpc = new ethers.JsonRpcProvider("https://evmrpc.0g.ai"); const wallet = ethers.Wallet.createRandom().connect(rpc); const broker = await createZGComputeNetworkBroker(wallet); // 1. Make the request so you can read headers const response = await fetch("https://router-api.0g.ai/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer sk-YOUR_API_KEY", }, body: JSON.stringify({ model: "glm-5.2", messages: [...] }), }); const data = await response.json(); // 2. Pull the two inputs processResponse needs const providerAddress = data.x_0g_trace.provider; const chatID = response.headers.get("ZG-Res-Key") ?? data.id; // 3. Verify independently — SDK reads the chain + calls the provider, not the Router const isValid = await broker.inference.processResponse(providerAddress, chatID); // true → independently verified // false → verification failed (treat response as untrusted) // null → provider has no verifiable TEE service (nothing to check) ``` Under the hood the SDK reads the provider's on-chain service record, fetches the signature from the provider, and verifies it against the TEE signer — the same work the Router does internally, but running on your side so you don't have to trust the Router's answer. ### Without the SDK If you prefer to verify from scratch (e.g. from a language without the 0G SDK), the four steps you'd reproduce are: 1. Read the provider's service record from the on-chain `Service` contract using the `provider` address. The record gives you `url`, `teeSignerAddress`, and `verifiability`. (If `additionalInfo.targetSeparated` is true, use `additionalInfo.targetTeeAddress` as the signer instead.) 2. `GET {url}/v1/proxy/signature/{chatID}?model={model}` — returns `{text, signature}`. 3. Verify the signature as EIP-191 `personal_sign` against `teeSignerAddress`. Any standard Ethereum library works. 4. Confirm the signed `text` matches the response content you received from the Router. All four steps pass → end-to-end cryptographic proof, no trust in the Router required. ## Related - [**Principles: Verifiable Execution**](../principles#4-verifiable-execution) — the "why" behind this feature - [**Chat Completions**](./chat-completions#response-shape) — structure of the `x_0g_trace` block - [**Provider Routing**](../routing) — pin to a specific attested provider with `X-0G-Provider-Address` --- ## Models Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/models.md The model catalog is served live by the Router. You can browse it two ways: - **Web UI** — **[pc.0g.ai](https://pc.0g.ai)** shows every model with current pricing, the number of healthy providers, and capability badges (streaming, tool calling, vision, etc.). - **API** — `GET /v1/models` returns the same data in OpenAI's list format. No authentication required. ## Listing Models ```bash curl https://router-api.0g.ai/v1/models ``` ```json { "object": "list", "data": [ { "id": "glm-5.2", "object": "model", "owned_by": "0G Foundation", "name": "GLM-5.2", "context_length": 1048576, "pricing": { "prompt": "4830000000000", "completion": "16120000000000" }, "provider_count": 3 } ] } ``` Prices are in **neuron per token** (1e18 neuron = 1 0G). Multiply by `input_tokens` / `output_tokens` to estimate cost. ## Capability Flags Not every model supports every feature. Before relying on **tool calling**, **vision input**, or **JSON mode**, check the model's entry in the Web UI or in the `/v1/models` response — capability flags are shown on each model card and in the API payload. If you send a `tools` field to a model that doesn't support it, the Router returns `400 Bad Request` rather than silently dropping the parameter. ## Listing Providers for a Model ```bash curl "https://router-api.0g.ai/v1/providers?model=glm-5.2" ``` Returns every TEE-acknowledged provider serving that model, with on-chain address, observed latency, and TEE attestation info. Use these addresses with the [`X-0G-Provider-Address` header](./routing) if you want deterministic routing. Each entry also carries `provider_identity` — the operator-declared name of the upstream channel serving that endpoint (for example `aliyun` or `openrouter`). It is a routing label, not an attested property; `verifiability` remains the trust signal. Endpoints serving a model through a single native channel omit the field. To route by channel, use the [`X-0G-Provider-Identity` header](./routing#header-reference) — it filters candidates rather than pinning one endpoint unless combined with an address. Independently of any pin, your usage history records which identity served each request. Query parameters: | Field | Description | | -------------- | ------------------------------------------------------------------ | | `model` | Filter to providers serving a specific model ID | | `service_type` | Filter by service type (e.g. `chatbot`, `text-to-image`, `speech-to-text`) | --- ## 0G Compute Router Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/overview.md The **0G Compute Router** is an API gateway that sits in front of the entire 0G Compute Network. One endpoint, one API key, every model. It handles provider discovery, on-chain billing, authentication, and failover automatically — so you use 0G's decentralized inference with the same code you'd write for OpenAI or Anthropic. ## When to Use the Router | | **Router** | **[Direct](../direct)** | | ------------------- | ----------------------------------- | ---------------------------------- | | Setup | Get an API key | Install SDK, manage wallet keys | | Provider management | Automatic routing + failover | Manual selection & funding | | Billing | Single unified on-chain balance | Per-provider sub-accounts | | API shape | OpenAI / Anthropic compatible | Custom SDK calls | | Best for | Server-side apps, agents, prototypes| Browser dApps, direct chain access | Pick the Router when you want the simplest integration path. Pick Direct when you need per-provider control or wallet-signed requests in the browser. ## 60-Second Tour **[Quickstart →](./quickstart)** Connect wallet, deposit, create an API key, send your first request — in four steps. **[Chat Completions →](./features/chat-completions)** OpenAI-compatible `/v1/chat/completions` with streaming, tool calling, and reasoning tokens. **[Provider Routing →](./routing)** Route by lowest latency, lowest price, or pin to a specific on-chain provider. **[Authentication →](./authentication)** API keys with three permission tiers. **[Models →](./models)** Browse the live catalog. Each model has pricing, context window, and capability flags. **[Deposits & Billing →](./account/deposits)** Deposit 0G tokens, consume on-chain, settle periodically. No subscriptions. ## Base URLs Mainnet and testnet are fully separate environments — different Web UI, different API endpoint, different on-chain balances and API keys. Pick the one that matches the network your wallet is on. | Network | Web UI | API Endpoint | | ----------- | --------------------------------------------------- | --------------------------------------------------------- | | **Mainnet** | [pc.0g.ai](https://pc.0g.ai) | `https://router-api.0g.ai/v1` | | **Testnet** | [pc.testnet.0g.ai](https://pc.testnet.0g.ai) | `https://router-api-testnet.integratenetwork.work/v1` | :::tip OpenAI SDK drop-in Any tool that speaks the OpenAI API works with 0G Router — change `base_url` and `api_key`, nothing else. ::: :::note Migrating from compute-marketplace.0g.ai? If you previously deposited on **[compute-marketplace.0g.ai](https://compute-marketplace.0g.ai)**, those funds live in **per-provider sub-accounts** under the [Direct](../direct) flow. They do **not** appear in the Router balance on pc.0g.ai — the two systems use different contracts and different accounting. To see and use those old funds on pc.0g.ai, switch to **Advanced** mode using the toggle in the top-right. Advanced mode is the same Direct flow, just embedded in the new UI. See [Router vs Advanced Mode](./comparison#pc0gai-router-vs-advanced-mode). ::: --- ## Principles Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/principles.md The Router exists to make 0G's decentralized compute network usable with the same code you already have. Four design choices shape how it works. ## 1. Drop-in Compatibility The Router speaks the **OpenAI API** (`/v1/chat/completions`, `/v1/images/generations`, `/v1/audio/transcriptions`, …). Same routes, same fields, same SSE format. Any SDK, agent framework, or tool that targets these APIs works without code changes — point it at `https://router-api.0g.ai/v1` and supply your Router API key. The goal is zero switching cost. If we add a feature that OpenAI doesn't have (like provider pinning), it lives in an optional top-level field that is stripped before the request reaches the underlying provider. Your existing requests keep working. ## 2. On-Chain Billing, No Subscriptions There is no monthly plan. You deposit 0G tokens to a payment contract, and each request debits the exact cost based on per-model token prices. Remaining balance is always visible on-chain. ```text total_cost = (input_tokens × prompt_price) + (output_tokens × completion_price) ``` Settlement to individual providers happens periodically in the background — you only see a single unified balance. Details: [Deposits & Billing](./account/deposits). ## 3. Failover by Default Each model is served by one or more independent providers. The Router health-checks them continuously and distributes requests round-robin across the healthy set. If a request fails, the Router retries on the next healthy provider before returning an error to you. You can override this — [Provider Routing](./routing) lets you sort by `latency` / `price` or pin to a specific provider address — but the default is "just work." ## 4. Verifiable Execution Every provider on the network runs inside a **Trusted Execution Environment (TEE)** and attests to the exact model it's serving. The Router exposes provider addresses and attestation metadata so you can verify, out-of-band, that your request was handled by a model you trust. This is the reason to use 0G over a centralized endpoint: you get OpenAI-style ergonomics **and** cryptographic proof that the model wasn't silently swapped. ## What the Router Does Not Do - **No prompt storage.** The Router does not persist request or response bodies. Only billing metadata (token counts, model, provider, timestamp) is stored. - **Provider isolation via TEE.** Every provider runs inside a Trusted Execution Environment, which isolates the serving process so it cannot access inference traffic outside the attested request/response path. - **No synthetic responses.** The Router never generates content itself. If no provider can serve the request, you get a `503` — not a fallback LLM. --- ## Data Privacy & Zero Data Retention Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/privacy.md This page describes exactly what happens to your data on the 0G Compute Router (pc.0g.ai): what is retained, what is never stored, and how to restrict routing to sealed-inference providers. ## Zero data retention The Router operates with zero data retention on inference content: - **Prompts and completions are processed in memory only** for the lifetime of the request: the Router handles them in memory to route and bill the request, and never writes them to storage. There is no conversation table and no response archive; billing records carry metadata only. - **0G does not train on your data.** Content that is never stored cannot be used for training. - **Multipart inputs are not stored.** Audio and image inputs sent to multipart endpoints are passed through in memory for the lifetime of the request and never persisted. The Router does not store generated images: results are returned to the caller and not kept. ### What is retained Billing and usage metadata only: | Field | Purpose | |-------|---------| | Request ID | Support and audit lookups | | Wallet address | Account attribution | | Model and provider | Per-model usage breakdowns | | Token counts (input / output / cached) | Billing | | Trust tier served | Per-tier audit (see below) | | Cost and timestamp | Billing and statements | None of these fields contain request content. ## Privacy mode In privacy mode, requests route **only to TeeML providers**: the model itself runs inside a Trusted Execution Environment (Intel TDX with TEE-enabled GPUs). The prompt enters the enclave encrypted, the response is signed inside the enclave, and the host machine sees only encrypted traffic. Neither 0G nor the provider operating the hardware can see the inference data or process. Every enclave publishes a hardware attestation verifiable with [dstack](https://github.com/Dstack-TEE/dstack). This is the `private` tier of [trust-mode routing](./routing.md#trust-modes): | Tier | Routes to | Guarantee | |------|-----------|-----------| | `private` | TeeML providers only | Sealed inference: prompts never leave the enclave | | `verified` | TeeML and TeeTLS providers | Verifiable execution: the response provably came from the real model | | `standard` | All providers, including third-party channels | Full model access. Non-verifiable: no attestation or signed proof to check | With TeeTLS, 0G's broker (itself running inside a TEE) relays your request over attested TLS and cannot read it in transit, but the upstream provider processes your prompt under its own data policy. `standard` places no restriction on the provider pool: it widens the catalog to third-party channels that are non-verifiable. The serving broker runs on TEE hardware with verification disabled and the upstream is not disclosed, so there is no attestation or signature to check on the response. Today the Claude and GPT-5.6 families are served on this tier; the live list is always the [models endpoint](#models-with-privacy-mode). If your requirement is that no third party ever sees plaintext, use `private`. :::note Model selection is not tier selection A request that does not set a trust mode can be served by **any** provider of the model, including `standard` ones, and the model list displays each model according to its **highest-capability** provider. When a model has multiple providers, the Router balances between them for performance. To guarantee a verifiable channel, pin the tier explicitly using one of the methods below. ::: For workloads that must not touch the Router at all, [Advanced mode](https://pc.0g.ai/sdk) connects your wallet directly to a provider: funding and inference happen entirely inside the decentralized network, with no intermediary in the path. ## Enabling privacy mode **Per API key** — in [pc.0g.ai](https://pc.0g.ai) open Dashboard → API Keys and set the key's trust mode to Private. Every request made with that key routes only to TeeML providers, regardless of what the calling code sends. Programmatically: `POST /v1/api-keys` with `"trust_mode": "private"` (requires an `mk-` management key, see [Authentication](./authentication.md)). **Per request** — send the routing header: ```python from openai import OpenAI client = OpenAI( base_url="https://router-api.0g.ai/v1", api_key="sk-YOUR_API_KEY", default_headers={"X-0G-Provider-Trust-Mode": "private"}, ) completion = client.chat.completions.create( model="glm-5.2", # served by a TeeML provider messages=[{"role": "user", "content": "Hello"}], ) ``` If no TeeML provider is available for the requested model, the request fails with a `503` and never silently falls back to a lower tier: ```json { "error": { "message": "no provider available for trust mode: tier=private", "type": "server_error", "code": "no_provider_for_trust_mode" } } ``` The condition is transient (tier supply, not permissions), so clients should retry or switch to a model with a TeeML provider. ## Models with privacy mode The live source of truth is the models endpoint: any model with `"verifiability": "TeeML"` accepts `private` requests. No authentication required: ```bash curl -s https://router-api.0g.ai/v1/models | jq '.data[] | select(.verifiability == "TeeML") | .name' ``` The catalog changes as providers join the network; per-provider tiers are shown on each model's detail page at pc.0g.ai. ## Auditing - Account usage endpoints break down consumption by trust tier, so you can report exactly which share of traffic ran sealed, per day and per model. - Add `verify_tee: true` to any request to have the Router verify the provider's TEE signature synchronously; see [Verifiable Execution](./features/verifiable-execution.md). - Provider attestations can be independently verified with [dstack-verifier](https://github.com/Dstack-TEE/dstack), and the verification mechanics are documented under [verification modes](../inference.md#verification-modes). --- ## Quickstart Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/quickstart.md Four steps. Five minutes. ## 1. Connect Your Wallet Visit **[pc.0g.ai](https://pc.0g.ai)** and connect a wallet. MetaMask and WalletConnect work directly; you can also sign in with Google, X/Twitter, Discord, or TikTok via Privy, which provisions an embedded wallet for you. ## 2. Deposit Funds Deposit 0G tokens to the Router's on-chain payment contract. Your balance lives on-chain and is debited per request. See [Deposits & Billing](./account/deposits) for how costs are calculated and how to check your balance. ## 3. Create an API Key In **Dashboard → API Keys**, click **Create**. You'll get a secret starting with `sk-` — the API key used for inference calls. See [Authentication](./authentication) for the difference between `sk-` API keys and `mk-` management keys. Store it somewhere safe — the Router never shows it again. ## 4. Send Your First Request ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -d '{ "model": "glm-5.2", "messages": [ {"role": "user", "content": "Hello!"} ] }' ``` ```python from openai import OpenAI client = OpenAI( base_url="https://router-api.0g.ai/v1", api_key="sk-YOUR_API_KEY", ) response = client.chat.completions.create( model="glm-5.2", messages=[{"role": "user", "content": "Hello!"}], ) print(response.choices[0].message.content) ``` ```javascript import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://router-api.0g.ai/v1", apiKey: "sk-YOUR_API_KEY", }); const response = await client.chat.completions.create({ model: "glm-5.2", messages: [{ role: "user", content: "Hello!" }], }); console.log(response.choices[0].message.content); ``` That's it. You're talking to a decentralized TEE-backed provider through an OpenAI-compatible API. ## Next Steps - **[Chat Completions](./features/chat-completions)** — streaming, tool calling, system prompts - **[Provider Routing](./routing)** — route by latency, price, or specific provider - **[Claude Code](./clients/claude-code)** — point Claude Code at the Router, including auto mode's permission gate - **[Models](./models)** — browse the catalog with live pricing --- ## Rate Limits Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/rate-limits.md The Router applies per-account request limits to keep the network responsive. The exact thresholds depend on your account state and may evolve as we tune them — this page documents how to **observe and react to** the limit, not the specific numbers. ## Response headers Every inference response includes rate-limit headers (OpenAI-compatible) so you can back off proactively without waiting for a `429`: ```http X-RateLimit-Limit-Requests: X-RateLimit-Remaining-Requests: X-RateLimit-Reset-Requests: ``` ## 429 Too Many Requests When you exceed the limit, the Router returns `429` immediately with a `Retry-After` header (seconds): ```http HTTP/1.1 429 Too Many Requests Retry-After: 15 Content-Type: application/json ``` ```json { "error": { "message": "Rate limit exceeded. Please try again later.", "type": "rate_limit_error", "code": "rate_limit_exceeded" } } ``` **Honor `Retry-After`.** Don't retry in a tight loop — the Router will keep returning `429` and your real requests will be delayed. ## Related - [**Errors**](./errors) - [**Deposits & Billing**](./account/deposits) :::info Coming soon Per-API-key throughput controls — explicit **RPM** (requests per minute) and **TPM** (tokens per minute) budgets settable in the dashboard — are on the roadmap. ::: --- ## Provider Routing Source: https://docs.0g.ai/developer-hub/building-on-0g/compute-network/router/routing.md By default, the Router distributes requests across healthy providers using round-robin with automatic failover. `X-0G-Provider-*` request headers let you override this when you need specific behavior. ## Default Behavior If you send no routing headers, the Router: 1. Picks a healthy provider for the requested model 2. Retries on the next healthy provider if the first returns an error 3. Returns the response — or a `503` if every provider failed This is the recommended path for most applications. ## Routing surfaces The Router accepts routing preferences from two surfaces. In priority order: | Priority | Surface | Endpoints | Status | | -------- | ------- | --------- | ------ | | 1 | `X-0G-Provider-*` request headers | All inference endpoints (JSON, multipart, async) | **Canonical** | | 2 | JSON body `provider: {…}` object | JSON endpoints only (`/v1/chat/completions`, `/v1/messages`, `/v1/images/generations`, `/v1/async/images/generations`) | Deprecated — kept for back-compat | Headers and body are merged field-by-field; when the same field is set on both, the header wins. Multipart endpoints (`/v1/audio/transcriptions`, `/v1/images/edits`, `/v1/async/images/edits`) have **no body routing surface** — headers are the only way to control routing there. :::caution The JSON body `provider` object is deprecated New code should use `X-0G-Provider-*` headers. The body surface still works today for back-compat but will be phased out in a future release. Headers are the only routing surface that works uniformly across JSON, multipart, and async endpoints. ::: ## Routing Strategies ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Sort: latency" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Routes to the provider with the lowest recently-observed latency for this model. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Sort: price" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Routes to the cheapest provider currently serving this model. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Max-Price-Usd-Prompt: 1.0" \ -H "X-0G-Provider-Max-Price-Usd-Completion: 5.0" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Drops every provider above the ceiling **before** sorting and failover, so even a fallback during an outage can't route you to a more expensive provider. See [Capping price per request](#capping-price-per-request). ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Address: 0xd9966e..." \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Routes directly to a specific provider by on-chain address. **Fallback is disabled by default when pinning by address** — if the pinned provider fails, the request fails. Add `X-0G-Provider-Allow-Fallbacks: true` to re-enable cross-provider retry. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Identity: aliyun" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Some models are served through more than one upstream channel. `provider_identity` is the operator-declared name of that channel (for example `aliyun`, `zhipu`, `openrouter`) — a routing label, not an attested property (`verifiability` remains the trust signal). It is shown per endpoint on [`GET /v1/providers`](./models#listing-providers-for-a-model) and matched verbatim (case-sensitive). The header works in two modes: - **Alone** — a filter, not a pin: it narrows the candidates for the model to every endpoint carrying that identity, possibly across several providers, then the normal ranking (your [`X-0G-Provider-Sort`](#header-reference) choice) picks among them. Fallback stays enabled but only across the matching endpoints — it never spills over to other identities. - **Combined with `X-0G-Provider-Address`** — pins the exact upstream variant under that provider address, and inherits the address pin's `Allow-Fallbacks: false` default. An identity that matches no endpoint fails deterministically, rejected with `400 provider_model_mismatch` — never a silent fallback to unfiltered routing. Other routing filters compose after the identity filter: if the identity's endpoints exist but none matches a requested [trust mode](#trust-modes), the request fails with `503 no_provider_for_trust_mode` instead. Endpoints that serve a model through a single native channel carry no identity (the field is omitted on `/v1/providers`); pin those by address. Multipart endpoints accept the same headers — this is the only routing surface available there. ```bash curl https://router-api.0g.ai/v1/audio/transcriptions \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Sort: latency" \ -F "file=@recording.mp3" \ -F "model=openai/whisper-large-v3" ``` The legacy JSON body surface still works on JSON endpoints. New code should prefer headers. ```json { "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}], "provider": { "sort": "latency" } } ``` When both surfaces are present and set the same field, the header wins. ## Header Reference HTTP header names are case-insensitive per RFC 7230 — `X-0G-Provider-Address` and `x-0g-provider-address` are equivalent. | Header | Values | Description | | ------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------ | | `X-0G-Provider-Address` | on-chain address (`0x…`) | Pin the request to a specific provider. Implies `Allow-Fallbacks: false` unless overridden. | | `X-0G-Provider-Identity` | upstream channel name (e.g. `aliyun`) | Route to a named upstream channel. Alone it filters candidates to that identity and normal ranking picks among them; with `X-0G-Provider-Address` it pins the exact variant and inherits `Allow-Fallbacks: false`. An identity matching no endpoint is rejected with `400 provider_model_mismatch`. | | `X-0G-Provider-Sort` | `latency` \| `price` | Sort strategy when no address is pinned. Ignored if `X-0G-Provider-Address` is set. Must be exactly `latency` or `price` — any other non-empty value is rejected with `400 invalid_provider_header`. | | `X-0G-Provider-Trust-Mode` | `standard` \| `verified` \| `private` | Restrict provider selection to a trust tier — see [Trust modes](#trust-modes). | | `X-0G-Provider-Allow-Fallbacks` | `true` \| `false` | Allow cross-provider retry on failure. Must be exactly `true` or `false` (case-insensitive) — `1`, `0`, `yes`, and other non-empty values are rejected with `400 invalid_provider_header`. | | `X-0G-Provider-Max-Price-Usd-Prompt` | finite, non-negative decimal | Per-request ceiling on prompt token price, USD per 1M tokens. See [Capping price per request](#capping-price-per-request). | | `X-0G-Provider-Max-Price-Usd-Completion` | finite, non-negative decimal | Per-request ceiling on completion token price, USD per 1M tokens. See [Capping price per request](#capping-price-per-request). | | `X-0G-Provider-Max-Price-Usd-Image` | finite, non-negative decimal | Per-request ceiling on image price, USD per generated image. See [Capping price per request](#capping-price-per-request). | Defaults: `Allow-Fallbacks` is `true` normally, and `false` when `X-0G-Provider-Address` is set. A header that is absent, or blank after trimming whitespace, is treated as unset and falls back to the default. Only a **present-but-malformed** value is rejected — a blank header meaning "I didn't set this" is never an error. ### Trust modes `X-0G-Provider-Trust-Mode` restricts selection by the provider's [verification mode](../inference#verification-modes). The tiers are ordered `standard < verified < private` and act as a floor: asking for `verified` is also satisfied by the stronger `private`. | Value | Routes to | Guarantee | | ---------- | ------------------------------ | --------------------------------------------------------------------------------------------------- | | `standard` | All providers, including third-party channels | Full model access. Non-verifiable: no attestation or signed proof to check. | | `verified` | TeeML **and** TeeTLS providers | Verifiable execution — the response provably came from the real model. | | `private` | TeeML providers only | Verifiability **and** privacy — the model itself runs inside the TEE, so prompts never leave the enclave. | Values other than `standard`/`verified`/`private` are rejected with `400 invalid_trust_mode`. Omit the header for no trust-tier restriction (the default) — an unrestricted request can be served by any provider of the model, including `standard` ones. ## Capping price per request The `X-0G-Provider-Max-Price-Usd-*` headers set a **hard ceiling** on what you're willing to pay. Any provider above the ceiling on a relevant dimension is dropped from the candidate pool entirely — this is a filter, not a preference, and it runs **before** sorting and failover. A fallback during an outage can never silently route you to a provider you've priced out. ```bash curl https://router-api.0g.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-YOUR_API_KEY" \ -H "X-0G-Provider-Max-Price-Usd-Prompt: 1.0" \ -H "X-0G-Provider-Max-Price-Usd-Completion: 5.0" \ -d '{ "model": "glm-5.2", "messages": [{"role": "user", "content": "Hello"}] }' ``` Send any subset — one header, two, or all three. Each value is a finite, non-negative decimal; `NaN`, `Inf`, negative, and non-numeric values are rejected with `400 invalid_max_price_usd`. ### Which dimension applies to which endpoint The ceiling is **service-type aware**. Setting `Image` on a chat call (or `Prompt` / `Completion` on an image call) is silently inert, so a cross-endpoint SDK that always sends all three headers won't accidentally filter out every provider. | Service type | Endpoints | Dimensions enforced | Unit | | ----------------------- | ----------------------------------------------------------- | ----------------------- | ---------------------- | | Chat | `/v1/chat/completions`, `/v1/messages` | `Prompt`, `Completion` | USD per 1M tokens | | Image | `/v1/images/generations`, `/v1/images/edits`, `/v1/async/images/*` | `Image` | USD per generated image | | Speech-to-text | `/v1/audio/transcriptions` | none yet — see below | — | :::note Speech-to-text is not covered yet STT models are billed per second of audio, which has no equivalent in the current USD pricing schema (`prompt` / `completion` / `image` only). Reusing the `Prompt` header for STT would be a footgun — the same `1.0` would mean "$1 per 1M tokens" on chat and "$1 per second" on audio — so `/v1/audio/transcriptions` enforces no ceiling for now. ::: Two failure modes are worth calling out: - **No provider qualifies.** If the ceiling filters out every candidate, the request fails with `400 no_provider_within_max_price`, not `503` — the pool is empty structurally, not transiently, so retrying without raising the ceiling won't help. - **Pinning + ceiling.** If `X-0G-Provider-Address` pins a provider above the ceiling, the request fails with `400 pinned_provider_exceeds_max_price` — the pin isn't silently overridden. ## Discovering Provider Addresses List the providers serving a model with `GET /v1/providers?model_id=…` — see [Models](./models#listing-providers-for-a-model). ## Related - [**Principles**](./principles) — why failover is the default - [**Errors**](./errors) — what `502` and `503` mean for routing --- ## Deploy Contracts on 0G Chain Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts.md Deploy smart contracts on 0G Chain - an EVM-compatible blockchain with built-in AI capabilities. ## Why Deploy on 0G Chain? ### ⚡ Performance Benefits - **11,000 TPS per Shard**: Higher throughput than Ethereum - **Low Fees**: Fraction of mainnet costs - **Sub-second Finality**: Near-instant transaction confirmation ### 🔧 Latest EVM Compatibility - **Pectra & Cancun-Deneb Support**: Leverage newest Ethereum capabilities - **Future-Ready**: Architecture designed for quick integration of upcoming EVM upgrades - **Familiar Tools**: Use Hardhat, Foundry, Remix - **No Learning Curve**: Deploy like any EVM chain ## Prerequisites Before deploying contracts on 0G Chain, ensure you have: - Node.js 16+ installed (for Hardhat/Truffle) - Rust installed (for Foundry) - A wallet with testnet 0G tokens ([get from faucet](https://faucet.0g.ai)) - Basic Solidity knowledge ## Steps to Deploy Your Contract ### Step 1: Prepare Your Smart Contract Code Write your contract code as you would for any Ethereum-compatible blockchain, ensuring that it meets the requirements for your specific use case. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; contract MyToken { mapping(address => uint256) public balances; uint256 public totalSupply; constructor(uint256 _initialSupply) { totalSupply = _initialSupply; balances[msg.sender] = _initialSupply; } function transfer(address to, uint256 amount) public returns (bool) { require(balances[msg.sender] >= amount, "Insufficient balance"); balances[msg.sender] -= amount; balances[to] += amount; return true; } } ``` ### Step 2: Compile Your Smart Contract Use `solc` or another compatible Solidity compiler to compile your smart contract. **Important**: When compiling, specify `--evm-version cancun` to ensure compatibility with the latest EVM upgrades supported by 0G Chain. **Using solc directly**: ```bash solc --evm-version cancun --bin --abi MyToken.sol ``` **Using Hardhat**: ```javascript // hardhat.config.js module.exports = { solidity: { version: "0.8.19", settings: { evmVersion: "cancun", optimizer: { enabled: true, runs: 200, }, }, }, }; ``` **Using Foundry**: ```toml # foundry.toml [profile.default] evm_version = "cancun" ``` This step will generate the binary and ABI (Application Binary Interface) for your contract. ### Step 3: Deploy the Contract on 0G Chain Once compiled, you can use your preferred Ethereum-compatible deployment tools, such as `web3.js`, `ethers.js`, or `hardhat`, to deploy the contract on 0G Chain. **Configure Network Connection**: ```javascript // For Hardhat networks: { "testnet": { url: "https://evmrpc-testnet.0g.ai", chainId: 16602, accounts: [process.env.PRIVATE_KEY] }, "mainnet": { url: "https://evmrpc.0g.ai", chainId: 16661, accounts: [process.env.PRIVATE_KEY] } } // For Foundry [rpc_endpoints] testnet = "https://evmrpc-testnet.0g.ai" mainnet = "https://evmrpc.0g.ai" ``` **Deploy Using Your Preferred Tool**:
Hardhat Deployment ```javascript // scripts/deploy.js async function main() { const MyToken = await ethers.getContractFactory("MyToken"); const token = await MyToken.deploy(1000000); // 1M initial supply await token.deployed(); console.log("Token deployed to:", token.address); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ``` Run: `npx hardhat run scripts/deploy.js --network testnet`
Foundry Deployment ```bash forge create --rpc-url https://evmrpc-testnet.0g.ai \ --private-key $PRIVATE_KEY \ --evm-version cancun \ src/MyToken.sol:MyToken \ --constructor-args 1000000 ```
Truffle Deployment ```javascript // migrations/2_deploy_token.js module.exports = function (deployer) { deployer.deploy(MyToken, 1000000); }; ``` Run: `truffle migrate --network testnet`
Follow the same deployment steps as you would on Ethereum, using your 0G Chain node or RPC endpoint. > For complete working examples using different frameworks, check out the official deployment scripts repository: 🔗 **[0G Deployment Scripts](https://github.com/0gfoundation/0g-deployment-scripts)** ### Step 4: Verify Deployment Results on 0G Chain Scan After deployment, you can verify your contract on 0G Chain Scan, the block explorer for **[0G Chain](https://chainscan.0g.ai)** or via the provided API below: Make sure you have the following plugins installed: ```bash npm install --save-dev @nomicfoundation/hardhat-verify @nomicfoundation/viem @nomicfoundation/hardhat-toolbox-viem dotenv ``` To verify your contract using Hardhat, please use the following settings in your `hardhat.config.js`: ```javascript solidity: { ... settings: { evmVersion: "cancun", // Make sure this matches your compiler setting optimizer: { enabled: true, runs: 200, // Adjust based on your optimization needs }, viaIR: true, // Enable if your contract uses inline assembly metadata: { bytecodeHash: "none", // Optional: Set to "none" to exclude metadata hash }, }, } ``` Add the network configuration: ```javascript networks: { "testnet": { url: "https://evmrpc-testnet.0g.ai", chainId: 16602, accounts: [process.env.PRIVATE_KEY] }, "mainnet": { url: "https://evmrpc.0g.ai", chainId: 16661, accounts: [process.env.PRIVATE_KEY] } } ``` and finally, add the etherscan configuration: ```javascript etherscan: { apiKey: { testnet: "YOUR_API_KEY", // Use a placeholder if you don't have one mainnet: "YOUR_API_KEY" // Use a placeholder if you don't have one }, customChains: [ { // Testnet network: "testnet", chainId: 16602, urls: { apiURL: "https://chainscan-galileo.0g.ai/open/api", browserURL: "https://chainscan-galileo.0g.ai", }, }, { // Mainnet network: "mainnet", chainId: 16661, urls: { apiURL: "https://chainscan.0g.ai/open/api", browserURL: "https://chainscan.0g.ai", }, }, ], }, ``` To verify your contract, run the following command: ```bash npx hardhat verify DEPLOYED_CONTRACT_ADDRESS --network ``` You should get a success message like this: ```bash Successfully submitted source code for contract contracts/Contract.sol:ContractName at DEPLOYED_CONTRACT_ADDRESS for verification on the block explorer. Waiting for verification result... Successfully verified contract TokenDist on the block explorer. https://chainscan.0g.ai/address/#code ``` On Foundry, you can verify your contract using the `forge verify-contract` command. Make sure to set your compiler settings in `foundry.toml` as needed. | Precompile | Verifier URL | | ---------- | ------------------------------------------ | | Testnet | `https://chainscan-galileo.0g.ai/open/api` | | Mainnet | `https://chainscan.0g.ai/open/api` | ```bash forge verify-contract \ --chain-id \ --num-of-optimizations \ --verifier custom \ --verifier-api-key "PLACEHOLDER" \ --compiler-version \ \ src/Counter.sol:Counter \ --verifier-url \ ``` You should get a success message like this: ```bash Submitted contract for verification: Response: OK GUID: URL: https://chainscan-galileo.0g.ai/open/address/ ``` ## Using 0G Precompiles ### Available Precompiles | Precompile | Address | Purpose | | -------------------------------------------------------- | ----------- | ---------------------------- | | [DASigners](./precompiles/precompiles-dasigners) | `0x...1000` | Data availability signatures | | [Wrapped0GBase](./precompiles/precompiles-wrappedogbase) | `0x...1002` | Wrapped 0G token operations | ## Troubleshooting
Transaction failing with "invalid opcode"? If you're using newer experimental opcodes from unreleased Ethereum upgrades and see "invalid opcode" errors, consider: - Use `--evm-version cancun` in your compiler settings - Downgrade to an earlier Solidity compiler version (e.g., from 0.8.26 to 0.8.19)
Can't connect to RPC? Try alternative endpoints: - QuikNode: [Get endpoint](https://www.quicknode.com/chains/0g) - ThirdWeb: [Get endpoint](https://thirdweb.com/16602)
## What's Next? - **Learn Precompiles**: [Precompiles Overview](./precompiles/precompiles-overview) - **Storage Integration**: [0G Storage SDK](/developer-hub/building-on-0g/storage/sdk) - **Compute Integration**: [0G Compute Guide](/developer-hub/building-on-0g/compute-network/overview) --- Need help? Join our [Discord](https://discord.gg/0glabs) for developer support. --- ## DASigners Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-dasigners.md ## Overview DAsigners is a wrapper for the `x/dasigners` module in the 0g chain, allowing querying the state of this module from EVM calls. ## Address `0x0000000000000000000000000000000000001000` ## ABI The ABI for encoding calls to the DASigners precompile (`0x0000000000000000000000000000000000001000`):
IDASigners ABI (JSON) ```json [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "signer", "type": "address" }, { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "indexed": false, "internalType": "struct BN254.G1Point", "name": "pkG1", "type": "tuple" }, { "components": [ { "internalType": "uint256[2]", "name": "X", "type": "uint256[2]" }, { "internalType": "uint256[2]", "name": "Y", "type": "uint256[2]" } ], "indexed": false, "internalType": "struct BN254.G2Point", "name": "pkG2", "type": "tuple" } ], "name": "NewSigner", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "signer", "type": "address" }, { "indexed": false, "internalType": "string", "name": "socket", "type": "string" } ], "name": "SocketUpdated", "type": "event" }, { "inputs": [], "name": "epochNumber", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "_epoch", "type": "uint256" }, { "internalType": "uint256", "name": "_quorumId", "type": "uint256" }, { "internalType": "bytes", "name": "_quorumBitmap", "type": "bytes" } ], "name": "getAggPkG1", "outputs": [ { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "internalType": "struct BN254.G1Point", "name": "aggPkG1", "type": "tuple" }, { "internalType": "uint256", "name": "total", "type": "uint256" }, { "internalType": "uint256", "name": "hit", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "_epoch", "type": "uint256" }, { "internalType": "uint256", "name": "_quorumId", "type": "uint256" } ], "name": "getQuorum", "outputs": [{ "internalType": "address[]", "name": "", "type": "address[]" }], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "_epoch", "type": "uint256" }, { "internalType": "uint256", "name": "_quorumId", "type": "uint256" }, { "internalType": "uint32", "name": "_rowIndex", "type": "uint32" } ], "name": "getQuorumRow", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address[]", "name": "_account", "type": "address[]" }], "name": "getSigner", "outputs": [ { "components": [ { "internalType": "address", "name": "signer", "type": "address" }, { "internalType": "string", "name": "socket", "type": "string" }, { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "internalType": "struct BN254.G1Point", "name": "pkG1", "type": "tuple" }, { "components": [ { "internalType": "uint256[2]", "name": "X", "type": "uint256[2]" }, { "internalType": "uint256[2]", "name": "Y", "type": "uint256[2]" } ], "internalType": "struct BN254.G2Point", "name": "pkG2", "type": "tuple" } ], "internalType": "struct IDASigners.SignerDetail[]", "name": "", "type": "tuple[]" } ], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "_account", "type": "address" }], "name": "isSigner", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "params", "outputs": [ { "components": [ { "internalType": "uint256", "name": "tokensPerVote", "type": "uint256" }, { "internalType": "uint256", "name": "maxVotesPerSigner", "type": "uint256" }, { "internalType": "uint256", "name": "maxQuorums", "type": "uint256" }, { "internalType": "uint256", "name": "epochBlocks", "type": "uint256" }, { "internalType": "uint256", "name": "encodedSlices", "type": "uint256" } ], "internalType": "struct IDASigners.Params", "name": "", "type": "tuple" } ], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "_epoch", "type": "uint256" }], "name": "quorumCount", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "internalType": "struct BN254.G1Point", "name": "_signature", "type": "tuple" } ], "name": "registerNextEpoch", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "signer", "type": "address" }, { "internalType": "string", "name": "socket", "type": "string" }, { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "internalType": "struct BN254.G1Point", "name": "pkG1", "type": "tuple" }, { "components": [ { "internalType": "uint256[2]", "name": "X", "type": "uint256[2]" }, { "internalType": "uint256[2]", "name": "Y", "type": "uint256[2]" } ], "internalType": "struct BN254.G2Point", "name": "pkG2", "type": "tuple" } ], "internalType": "struct IDASigners.SignerDetail", "name": "_signer", "type": "tuple" }, { "components": [ { "internalType": "uint256", "name": "X", "type": "uint256" }, { "internalType": "uint256", "name": "Y", "type": "uint256" } ], "internalType": "struct BN254.G1Point", "name": "_signature", "type": "tuple" } ], "name": "registerSigner", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_account", "type": "address" }, { "internalType": "uint256", "name": "_epoch", "type": "uint256" } ], "name": "registeredEpoch", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "string", "name": "_socket", "type": "string" }], "name": "updateSocket", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] ```
## Interface ### Structs #### `SignerDetail` ```solidity struct SignerDetail { address signer; string socket; BN254.G1Point pkG1; BN254.G2Point pkG2; } ``` - **Description**: Contains details of a signer, including the address, socket, and bn254 public keys (G1 and G2 points). - **Fields**: - `signer`: The address of the signer. - `socket`: The socket associated with the signer. - `pkG1`: The G1 public key of the signer. - `pkG2`: The G2 public key of the signer. #### `Params` ```solidity struct Params { uint tokensPerVote; uint maxVotesPerSigner; uint maxQuorums; uint epochBlocks; uint encodedSlices; } ``` - **Description**: Defines parameters for the DAsigners module. - **Fields**: - `tokensPerVote`: The number of tokens required for one vote. - `maxVotesPerSigner`: The maximum number of votes a signer can cast. - `maxQuorums`: The maximum number of quorums allowed. - `epochBlocks`: The number of blocks in an epoch. - `encodedSlices`: The number of encoded slices in one DA blob. --- ### Functions #### `params()` ```solidity function params() external view returns (Params memory); ``` - **Description**: Retrieves the current parameters of the DAsigners module. - **Returns**: `Params` structure containing the current module parameters. --- #### `epochNumber()` ```solidity function epochNumber() external view returns (uint); ``` - **Description**: Returns the current epoch number. - **Returns**: `uint` representing the current epoch number. --- #### `quorumCount(uint _epoch)` ```solidity function quorumCount(uint _epoch) external view returns (uint); ``` - **Description**: Returns the number of quorums for a given epoch. - **Parameters**: - `_epoch`: The epoch number. - **Returns**: `uint` representing the quorum count for the given epoch. --- #### `isSigner(address _account)` ```solidity function isSigner(address _account) external view returns (bool); ``` - **Description**: Checks if a given account is a registered signer. - **Parameters**: - `_account`: The address to check. - **Returns**: `bool` indicating whether the account is a signer. --- #### `getSigner(address[] memory _account)` ```solidity function getSigner( address[] memory _account ) external view returns (SignerDetail[] memory); ``` - **Description**: Retrieves details for the signers of the provided addresses. - **Parameters**: - `_account`: An array of addresses to fetch the signer details for. - **Returns**: An array of `SignerDetail` structures for each signer. --- #### `getQuorum(uint _epoch, uint _quorumId)` ```solidity function getQuorum( uint _epoch, uint _quorumId ) external view returns (address[] memory); ``` - **Description**: Returns the addresses of the members in a specific quorum for a given epoch. - **Parameters**: - `_epoch`: The epoch number. - `_quorumId`: The ID of the quorum. - **Returns**: An array of addresses that are members of the quorum. --- #### `getQuorumRow(uint _epoch, uint _quorumId, uint32 _rowIndex)` ```solidity function getQuorumRow( uint _epoch, uint _quorumId, uint32 _rowIndex ) external view returns (address); ``` - **Description**: Retrieves a specific address from a quorum's row for a given epoch and quorum ID. - **Parameters**: - `_epoch`: The epoch number. - `_quorumId`: The quorum ID. - `_rowIndex`: The row index within the quorum. - **Returns**: The address at the specified row index in the quorum. --- #### `registerSigner(SignerDetail memory _signer, BN254.G1Point memory _signature)` ```solidity function registerSigner( SignerDetail memory _signer, BN254.G1Point memory _signature ) external; ``` - **Description**: Registers a new signer with the provided details and signature. - **Parameters**: - `_signer`: The details of the signer to register. - `_signature`: The signature to verify the registration. --- #### `updateSocket(string memory _socket)` ```solidity function updateSocket(string memory _socket) external; ``` - **Description**: Updates the socket used by the module. - **Parameters**: - `_socket`: The new socket address to update. --- #### `registeredEpoch(address _account, uint _epoch)` ```solidity function registeredEpoch( address _account, uint _epoch ) external view returns (bool); ``` - **Description**: Checks if a specific account is registered in a given epoch. - **Parameters**: - `_account`: The address to check. - `_epoch`: The epoch number. - **Returns**: `bool` indicating whether the account is registered for the specified epoch. --- #### `registerNextEpoch(BN254.G1Point memory _signature)` ```solidity function registerNextEpoch(BN254.G1Point memory _signature) external; ``` - **Description**: Registers the next epoch using the provided signature. - **Parameters**: - `_signature`: The signature used to register the next epoch. --- #### `getAggPkG1(uint _epoch, uint _quorumId, bytes memory _quorumBitmap)` ```solidity function getAggPkG1( uint _epoch, uint _quorumId, bytes memory _quorumBitmap ) external view returns (BN254.G1Point memory aggPkG1, uint total, uint hit); ``` - **Description**: Retrieves the aggregated public key for a given epoch and quorum ID. - **Parameters**: - `_epoch`: The epoch number. - `_quorumId`: The quorum ID. - `_quorumBitmap`: The quorum bitmap. - **Returns**: - `aggPkG1`: The aggregated public key. - `total`: The number of rows. - `hit`: The number of rows that contributed to the aggregation. --- ## 0G Chain Precompiles Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-overview.md Precompiled contracts that extend 0G Chain with powerful native features for AI and blockchain operations. ## What Are Precompiles? Precompiles are special contracts deployed at fixed addresses that execute native code instead of EVM bytecode. They provide: - **Gas Efficiency**: 10-100x cheaper than Solidity implementations - **Native Features**: Access chain-level functionality - **Complex Operations**: Cryptographic functions and state management ## 0G Chain Precompiles Beyond standard Ethereum precompiles, 0G Chain adds specialized contracts for decentralized AI infrastructure: ### 🔐 [DASigners](./precompiles-dasigners) `0x0000000000000000000000000000000000001000` Manages data availability signatures for 0G's DA layer. **Key Features**: - Register and manage DA node signers - Query quorum information - Verify data availability proofs **Common Use Case**: Building applications that need to verify data availability directly on-chain. ### 🪙 [Wrapped0GBase](./precompiles-wrappedogbase) `0x0000000000000000000000000000000000001002` Wrapped version of native 0G token for DeFi compatibility. **Key Features**: - Wrap/unwrap native 0G tokens - ERC20-compatible interface - Efficient gas operations **Common Use Case**: Integrating 0G tokens with DEXs, lending protocols, or other DeFi applications. --- Questions? Get help in our [Discord](https://discord.gg/0glabs) #dev-support channel. --- ## Wrapped 0G Base Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-wrappedogbase.md ## Overview Wrapped0GBase is a wrapper for the `x/wrapped-og-base` module in the 0g chain. W0G is a wrapped ERC20 token for native 0G. It supports quota-based mint/burn functions based on native 0G transfers, on top of traditional wrapped token implementation. The minting/burning quota for each address will be determined through governance voting. `x/wrapped-og-base` is the module that supports and maintains the minting/burning quota. In most cases this precompile should be only called by wrapped 0G contract. ## Address `0x0000000000000000000000000000000000001002` > **Wrapped 0G Token Contract Address**: `0x1Cd0690fF9a693f5EF2dD976660a8dAFc81A109c` > > This is the official address of the wrapped 0G (W0G) ERC20 token on the 0G chain. Use this address if you want to interact directly with the wrapped 0G token contract for transfers, approvals, or other ERC20 operations. ## ABI The ABI for encoding calls to the Wrapped 0G Base precompile (`0x0000000000000000000000000000000000001002`):
IWrappedA0GIBase ABI (JSON) ```json [ { "inputs": [ { "internalType": "address", "name": "minter", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "burn", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "getWA0GI", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "minter", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "minter", "type": "address" }], "name": "minterSupply", "outputs": [ { "components": [ { "internalType": "uint256", "name": "cap", "type": "uint256" }, { "internalType": "uint256", "name": "initialSupply", "type": "uint256" }, { "internalType": "uint256", "name": "supply", "type": "uint256" } ], "internalType": "struct Supply", "name": "", "type": "tuple" } ], "stateMutability": "view", "type": "function" } ] ```
## Interface ### Structs #### `Supply` ```solidity struct Supply { uint256 cap; uint256 initialSupply; uint256 supply; } ``` - **Description**: Defines the supply details of a minter, including the cap, initial supply, and the current supply. - **Fields**: - `cap`: The maximum allowed mint supply for the minter. - `initialSupply`: The initial mint supply to the minter, equivalent to the initial allowed burn amount. - `supply`: The current mint supply used by the minter, set to `initialSupply` at beginning. --- ### Functions #### `getWA0GI()` ```solidity function getWA0GI() external view returns (address); ``` - **Description**: Retrieves the address of the wrapped 0G token from the wrapped 0G precompile. - **Returns**: `address` of the W0G contract. --- #### `minterSupply(address minter)` ```solidity function minterSupply(address minter) external view returns (Supply memory); ``` - **Description**: Retrieves the mint supply details for a given minter. - **Parameters**: - `minter`: The address of the minter. - **Returns**: A `Supply` structure containing the mint cap, initial supply, and current supply of the specified minter. --- #### `mint(address minter, uint256 amount)` ```solidity function mint(address minter, uint256 amount) external; ``` - **Description**: Mints 0G to WA0GI contract and adds the corresponding amount to the minter's mint supply. If the minter's final mint supply exceeds their mint cap, the transaction will revert. - **Parameters**: - `minter`: The address of the minter. - `amount`: The amount of 0G to mint. - **Restrictions**: Can only be called by the WA0GI contract. --- #### `burn(address minter, uint256 amount)` ```solidity function burn(address minter, uint256 amount) external; ``` - **Description**: Burns the specified amount of 0G in WA0GI contract on behalf of the minter and reduces the corresponding amount from the minter's mint supply. - **Parameters**: - `minter`: The address of the minter. - `amount`: The amount of 0G to burn. - **Restrictions**: Can only be called by the W0G contract. --- ## Staking Interfaces Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/staking-interfaces.md Welcome to the 0G Chain Staking Interfaces documentation. This guide provides comprehensive information about interacting with the 0G Chain staking system through smart contracts, enabling you to build applications that leverage validator operations and delegations. :::tip **Running a Validator?** If you want to set up and initialize a validator, see the [Validator Initialization Guide](#validator-initialization) below. ::: ## Quick Navigation - **[Validator Initialization Guide](#validator-initialization)** - Complete step-by-step setup for becoming a validator - **[Contract Interfaces](#contract-interfaces)** - Smart contract reference documentation - **[Examples](#examples)** - Smart contract code examples --- ## Overview The 0G Chain staking system enables 0G token holders to participate in network consensus and earn rewards through two primary mechanisms: 1. **Becoming a Validator**: Run infrastructure to validate transactions and produce blocks 2. **Delegating to Validators**: Stake tokens with existing validators to earn rewards without running infrastructure The staking system is built on two core smart contract interfaces: - **`IStakingContract`**: Central registry managing validators and global staking parameters - **`IValidatorContract`**: Individual validator operations including delegations and reward distribution ## Prerequisites Before working with the staking interfaces: - Familiarity with Solidity and smart contract development - Basic knowledge of consensus mechanisms and staking concepts ## Quick Start ```solidity // Create a validator IStakingContract staking = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9); address validator = staking.createAndInitializeValidatorIfNecessary{value: msg.value}( description, commissionRate, withdrawalFee, pubkey, signature ); // Delegate to validator IValidatorContract(validator).delegate{value: msg.value}(msg.sender); ``` ## Core Concepts ### Validators Validators process transactions and produce blocks: - **Unique Identity**: Identified by 48-byte consensus public key - **Operator Control**: Managed by an Ethereum address - **Commission**: Set their own reward commission rates - **Self-Delegation**: Required minimum stake from operator ### Delegations Token holders earn rewards by delegating to validators: - **Share-Based**: Delegations represented as shares in validator pool - **Proportional Rewards**: Earnings based on share percentage - **Withdrawal Delay**: Undelegation subject to network delay period ### Reward Distribution Rewards flow through multiple layers: 1. **Community Tax**: Applied to all rewards first 2. **Validator Commission**: Taken from remaining rewards 3. **Delegator Distribution**: Proportional to shares held ## Contract Interfaces ### IStakingContract `0xea224dBB52F57752044c0C86aD50930091F561B9` (Mainnet) Central registry for validators and global parameters. #### Validator Management ```solidity // Create validator contract function createValidator(bytes calldata pubkey) external returns (address); // Initialize validator with self-delegation function initializeValidator( Description calldata description, uint32 commissionRate, uint96 withdrawalFeeInGwei, bytes calldata pubkey, bytes calldata signature ) external payable; // Create and initialize in one call function createAndInitializeValidatorIfNecessary( Description calldata description, uint32 commissionRate, uint96 withdrawalFeeInGwei, bytes calldata pubkey, bytes calldata signature ) external payable; ``` #### Query Functions ```solidity function getValidator(bytes memory pubkey) external view returns (address); function computeValidatorAddress(bytes calldata pubkey) external view returns (address); function validatorCount() external view returns (uint32); function maxValidatorCount() external view returns (uint32); ``` ### IValidatorContract Individual validator operations and delegation management. #### Delegation Management ```solidity // Delegate tokens (msg.value = amount) function delegate(address delegatorAddress) external payable returns (uint); // Undelegate shares (msg.value = withdrawal fee) function undelegate(address withdrawalAddress, uint shares) external payable returns (uint); // Withdraw validator commission (only validator operator) function withdrawCommission(address withdrawalAddress) external returns (uint); ``` :::info **Access Control** The `withdrawCommission` function is restricted to the validator operator only - the address that originally created and manages the validator. ::: #### Information Queries ```solidity function tokens() external view returns (uint); // Total tokens (delegated + rewards) function delegatorShares() external view returns (uint); // Total shares issued function getDelegation(address delegator) external view returns (address, uint); function commissionRate() external view returns (uint32); function withdrawalFeeInGwei() external view returns (uint96); ``` :::tip **Understanding tokens()** The `tokens()` function returns the complete validator balance, including both the original delegated amounts and any accumulated rewards that haven't been distributed yet. ::: ## Examples ### Creating a Validator ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IStakingContract.sol"; contract ValidatorExample { IStakingContract constant STAKING = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9); function createValidator( bytes calldata pubkey, bytes calldata signature ) external payable { Description memory desc = Description({ moniker: "My Validator", identity: "keybase-id", website: "https://validator.example.com", securityContact: "security@example.com", details: "A reliable 0G Chain validator" }); STAKING.createAndInitializeValidatorIfNecessary{value: msg.value}( desc, 50000, // 5% commission 1, // 1 Gwei withdrawal fee pubkey, signature ); } } ``` ### Delegation Management ```solidity contract DelegationHelper { IStakingContract constant STAKING = IStakingContract(0xea224dBB52F57752044c0C86aD50930091F561B9); function delegateToValidator(bytes calldata pubkey) external payable { address validator = STAKING.getValidator(pubkey); require(validator != address(0), "Validator not found"); IValidatorContract(validator).delegate{value: msg.value}(msg.sender); } function getDelegationInfo( bytes calldata pubkey, address delegator ) external view returns (uint shares, uint estimatedTokens) { address validator = STAKING.getValidator(pubkey); IValidatorContract v = IValidatorContract(validator); (, shares) = v.getDelegation(delegator); uint totalTokens = v.tokens(); uint totalShares = v.delegatorShares(); if (totalShares > 0) { estimatedTokens = (shares * totalTokens) / totalShares; } } } ``` ## Validator Initialization This section covers the complete workflow for setting up and initializing a validator on the 0G Chain. ### Step 1: Generate Validator Signature The validator signature creation process is simplified with a single command: ```bash # Set your environment variables HOMEDIR={your data path}/0g-home/0gchaind-home STAKING_ADDRESS=0xea224dBB52F57752044c0C86aD50930091F561B9 AMOUNT=500000000000 # Amount in wei (e.g., 500 for 500 0G tokens) # Generate validator signature ./bin/0gchaind deposit create-delegation-validator \ $STAKING_ADDRESS \ $AMOUNT \ $HOMEDIR/config/genesis.json \ --home $HOMEDIR \ --chaincfg.chain-spec=mainnet \ --override-rpc-url \ --rpc-dial-url https://evmrpc.0g.ai ``` **Output:** ```text ✅ Staking message created successfully! Note: This is NOT a transaction receipt; use these values to create a validator initialize transaction by Staking Contract. stakingAddress: 0xea224dBB52F57752044c0C86aD50930091F561B9 pubkey: 0x8497312cd37eef3a7a50017cfbebcb00a9bc400c5881ffb1011cba1c3f29e5d005a980880b7b919b558b95565bc1e628 validatorAddress: 0xA47171b1be26C75732766Ea3433a90A724b3590d amount: 500000000000 signature: 0xb1dae1164d931c46178785246203eb1c4496b403a7c417bfb33bdfd3c26b552bdbec8e466ed6712ade0b99cc9b0ee8b004cc766687565ba5b0929a1382997a6cc548cf5e390b69f849933c7ac017fbddc612cb3de285fdf89e6fe32e0ccbfc43 ``` ### Step 2: Validate the Signature Before submitting the validator initialization transaction, validate the signature: ```bash # Validate the deposit message ./bin/0gchaind deposit validate-delegation \ {pubkey} \ {staking_address} \ {amount} \ {signature} \ $HOMEDIR/config/genesis.json \ --home $HOMEDIR \ --chaincfg.chain-spec=mainnet \ --override-rpc-url \ --rpc-dial-url https://evmrpc.0g.ai ``` **Example:** ```bash ./bin/0gchaind deposit validate-delegation \ 0x8497312cd37eef3a7a50017cfbebcb00a9bc400c5881ffb1011cba1c3f29e5d005a980880b7b919b558b95565bc1e628 \ 0xea224dBB52F57752044c0C86aD50930091F561B9 \ 500000000000 \ 0xb1dae1164d931c46178785246203eb1c4496b403a7c417bfb33bdfd3c26b552bdbec8e466ed6712ade0b99cc9b0ee8b004cc766687565ba5b0929a1382997a6cc548cf5e390b69f849933c7ac017fbddc612cb3de285fdf89e6fe32e0ccbfc43 \ $HOMEDIR/config/genesis.json \ --home $HOMEDIR \ --chaincfg.chain-spec=mainnet \ --override-rpc-url \ --rpc-dial-url https://evmrpc.0g.ai ``` **Output:** ```text ✅ Deposit message is valid! ``` ### Step 3: Prepare Validator Description and Settings #### Description Structure The Description struct contains your validator's public information. All fields have character limits that must be respected: | Field | Max Length | Description | |-------|-----------|-------------| | `moniker` | 70 chars | Your validator's display name | | `identity` | 100 chars | **Optional:** Keybase identity | | `website` | 140 chars | Your validator website URL | | `securityContact` | 140 chars | Security contact email | | `details` | 200 chars | Additional validator description | **Example Description Object:** ```jsx { moniker: "Your Validator Name", // Max 70 chars identity: "keybase_id", // Optional website: "https://yoursite.com", // Max 140 chars securityContact: "security@you.com", // Max 140 chars details: "Professional validator" // Max 200 chars } ``` #### Commission Rate Configuration The commission rate determines what percentage of staking rewards your validator keeps | Value | Commission | |-------|-----------| | `100` | 0.01% | | `1000` | 0.1% | | `10000` | 1% | | `50000` | 5% | | `100000` | 10% | #### Withdrawal Fee Configuration The withdrawal fee (in Gwei) is charged when delegators undelegate from your validator. **Recommended value:** `1` (equivalent to 1 Gneuron, ~1 Gwei) ### Step 4: Execute Initialization Transaction The easiest way to initialize your validator using the web interface: 1. Navigate to https://chainscan.0g.ai/address/0xea224dBB52F57752044c0C86aD50930091F561B9 2. Under **Contracts** Tab, click on the **Write As Proxy** button 3. Find and click on `createAndInitializeValidatorIfNecessary` 4. Fill in all the required parameters: - **description** (struct): - `moniker`: Your validator name (max 70 chars) - `identity`: Keybase ID (optional) - `website`: Your website URL - `securityContact`: Security contact email - `details`: Additional description - **commissionRate**: Commission percentage (e.g., 10000 for 1%) - **withdrawalFeeInGwei**: Withdrawal fee in Gwei (e.g.,1 Gneuron ~ 1 Gwei) - **pubkey**: The public key from Step 1 - **signature**: The signature from Step 1 5. Set the `payable amount` to **500** OG tokens 6. Connect your wallet and execute the transaction :::tip **Tip** Using the Chain Scan interface requires no coding knowledge and is the safest option for most users. ::: For users comfortable with wallet interactions: 1. Ensure your wallet is connected to **0G Chain Mainnet** 2. Go to the contract address: `0xea224dBB52F57752044c0C86aD50930091F561B9` 3. Use a contract interaction tool like: - [0G Chain Scan](https://chainscan.0g.ai) - Your wallet's built-in contract interaction features 4. Call `createAndInitializeValidatorIfNecessary` with: - `description`: Struct with all validator details - `commissionRate`: Commission percentage (e.g., 10000 for 1%) - `withdrawalFeeInGwei`: Withdrawal fee in Gwei (~1 Gneuron equivalent) - `pubkey`: Your validator's public key - `signature`: Your validator's signature 5. Set transaction value to **500 OG tokens** (500000000000000000000 wei) 6. Confirm the transaction in your wallet :::warning **Important** Ensure your wallet has sufficient funds: - 500 OG tokens for initialization - Additional gas fees for the transaction ::: For developers who want to automate the process: ```javascript const { ethers } = require("ethers"); // Initialize provider and wallet const provider = new ethers.JsonRpcProvider("https://evmrpc.0g.ai"); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider); // Staking contract ABI (minimal) const stakingABI = [ { "inputs": [ { "components": [ { "internalType": "string", "name": "moniker", "type": "string" }, { "internalType": "string", "name": "identity", "type": "string" }, { "internalType": "string", "name": "website", "type": "string" }, { "internalType": "string", "name": "securityContact", "type": "string" }, { "internalType": "string", "name": "details", "type": "string" } ], "internalType": "struct IStakingContract.Description", "name": "description", "type": "tuple" }, { "internalType": "uint32", "name": "commissionRate", "type": "uint32" }, { "internalType": "uint96", "name": "withdrawalFeeInGwei", "type": "uint96" }, { "internalType": "bytes", "name": "pubkey", "type": "bytes" }, { "internalType": "bytes", "name": "signature", "type": "bytes" } ], "name": "createAndInitializeValidatorIfNecessary", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "payable", "type": "function" } ]; async function initializeValidator() { const stakingContract = new ethers.Contract( "0xea224dBB52F57752044c0C86aD50930091F561B9", stakingABI, wallet ); const description = { moniker: "Your Validator Name", identity: "keybase_id", website: "https://yourvalidator.com", securityContact: "security@yourvalidator.com", details: "Professional 0G Chain validator" }; try { const tx = await stakingContract.createAndInitializeValidatorIfNecessary( description, 10000, // 1% commission 1000000, // 1 Gwei withdrawal fee "0x...", // Your pubkey "0x...", // Your signature { value: ethers.parseEther("500") } // 500 OG tokens ); console.log("Transaction hash:", tx.hash); const receipt = await tx.wait(); console.log("Validator initialized successfully!"); console.log("Transaction receipt:", receipt); } catch (error) { console.error("Error initializing validator:", error); } } initializeValidator(); ``` :::note **Environment Setup** Make sure to set `PRIVATE_KEY` in your `.env` file before running the script. ::: ### Step 5: Verify Initialization After successful initialization, you can verify your validator status: - Check the transaction on **0G Chain Scan**: https://chainscan.0g.ai - Verify your validator status on **0G Explorer**: https://explorer.0g.ai/mainnet/validators :::info **Activation Time** Your validator may initially appear as **inactive** on the explorer. This is normal. Validators typically take **30-60 minutes** to activate on the network after successful initialization. You can check the transaction status and logs to confirm the initialization was successful while waiting for activation. ::: ### Troubleshooting
Error: "Insufficient funds" Ensure you have at least 500 OG tokens plus gas fees in your wallet. ```bash # Check balance cast balance $YOUR_ADDRESS --rpc-url https://evmrpc.0g.ai ```
Error: "Validator already exists" Your validator has already been created. Use the `getValidator` function to retrieve your validator address: ```javascript const validatorAddress = await stakingContract.getValidator("0x..."); ```
Error: "Invalid signature" Regenerate your signature using 0gchaind with the correct validator contract address and delegation amount: ```bash ./bin/0gchaind deposit create-delegation-validator \ 0xea224dBB52F57752044c0C86aD50930091F561B9 \ 500000000000 \ $HOMEDIR/config/genesis.json \ --home $HOMEDIR \ --chaincfg.chain-spec=mainnet \ --override-rpc-url \ --rpc-dial-url https://evmrpc.0g.ai ```
Error: "Description field too long" Ensure all Description fields are within character limits: - `moniker`: max 70 chars - `identity`: max 100 chars - `website`: max 140 chars - `securityContact`: max 140 chars - `details`: max 200 chars
## Data Structures
Description Struct ```solidity struct Description { string moniker; // max 70 chars - Validator display name string identity; // max 100 chars - Keybase identity string website; // max 140 chars - Website URL string securityContact; // max 140 chars - Security contact string details; // max 200 chars - Additional details } ```
Withdrawal Entry ```solidity struct WithdrawEntry { uint completionHeight; // Block height when withdrawal completes address delegatorAddress; // Address receiving withdrawal uint amount; // Amount being withdrawn } ```
## Configuration Parameters | Parameter | Description | |-----------|-------------| | `maxValidatorCount` | Maximum validators allowed | | `minActivationStakesInGwei` | Minimum stake for activation | | `maxEffectiveStakesInGwei` | Maximum effective stake | | `communityTaxRate` | Tax on all rewards | | `minWithdrawabilityDelay` | Withdrawal delay blocks | ## General Troubleshooting
Error: "Validator not found" The validator hasn't been created yet. Use `createValidator()` first: ```solidity address validator = staking.createValidator(pubkey); ```
Error: "DelegationBelowMinimum" Your delegation amount is below the minimum required. Check: ```solidity uint96 minDelegation = staking.effectiveDelegationInGwei(); require(msg.value >= minDelegation * 1 gwei, "Insufficient delegation"); ```
Error: "NotEnoughWithdrawalFee" Include the withdrawal fee when undelegating: ```solidity uint96 fee = validator.withdrawalFeeInGwei(); validator.undelegate{value: fee * 1 gwei}(recipient, shares); ```
## Contract Addresses | Network | Staking Contract | |---------|------------------| | **Mainnet** | `0xea224dBB52F57752044c0C86aD50930091F561B9` | ## Resources - **Run Validator Node**: [Validator Setup Guide](../../../run-a-node/validator-node) - **Deploy Contracts**: [Contract Deployment](./deploy-contracts) --- Need help? Join our [Discord](https://discord.gg/0glabs) for developer support. --- ## Validator Contract Functions Source: https://docs.0g.ai/developer-hub/building-on-0g/contracts-on-0g/validator-contract-functions.md Complete function reference for individual validator contracts on 0G Chain. :::info **Quick Links** - **[Validator Initialization](./staking-interfaces#validator-initialization)** - Set up a new validator - **[Staking Interfaces](./staking-interfaces)** - Main staking system overview ::: ## Function Types ### View Functions (Free to Call) Query validator state without gas costs. ### Write Functions (Require Gas) Modify validator state - cost gas to execute. --- ## View Functions ### Validator Information #### `consensusPubkey()` Returns the validator's BLS public key. **Returns**: 48-byte BLS public key --- #### `operatorAddress()` Returns the validator operator's wallet address. **Returns**: Operator address --- #### `description()` Returns validator metadata. **Returns**: - Moniker (name) - Identity (verification key) - Website - Security contact - Details --- #### `commissionRate()` Returns current commission rate. **Returns**: Rate in parts per million (e.g., 100000 = 10%) --- #### `withdrawalFeeInGwei()` Returns fee charged for withdrawals. **Returns**: Fee in Gwei --- #### `bondStatus()` Returns validator's current status. **Returns**: - `Unspecified` - Not activated - `Bonded` - Active - `Unbonding` - Exiting - `Unbonded` - Fully exited --- ### Delegation Queries #### `tokens()` Returns total tokens delegated to this validator. **Returns**: Total tokens in Wei --- #### `delegatorShares()` Returns total shares issued. **Returns**: Total shares --- #### `getDelegation(address delegator)` Returns delegation info for a specific delegator. **Parameters**: - `delegator` - Delegator's address **Returns**: - Validator address - Number of shares owned --- #### `convertToTokens(uint shares)` Converts shares to token amount. **Parameters**: - `shares` - Number of shares **Returns**: Equivalent token amount **Use Case**: Calculate token value of your shares --- #### `convertToShares(uint tokens)` Converts tokens to shares. **Parameters**: - `tokens` - Token amount **Returns**: Equivalent shares **Use Case**: Calculate shares you'll receive when delegating --- ### Rewards & Earnings #### `rewards()` Returns accumulated rewards pending distribution. **Returns**: Reward amount in Wei --- #### `commission()` Returns accumulated commission earned by operator. **Returns**: Commission in Wei --- #### `tipFee()` Returns withdrawable tip fees. **Returns**: Tip fee amount in Wei **Calculation**: Contract balance - (commission + rewards + stakes + pending withdrawals) --- #### `stakes()` Returns amount actively staked in beacon chain. **Returns**: Staked amount in Wei --- #### `annualPercentageYield()` Returns current APY. **Returns**: APY in basis points (e.g., 1500 = 15%) --- ### Withdrawal Queue #### `withdrawCount()` Returns number of pending withdrawals. **Returns**: Count of pending withdrawals --- #### `getWithdraw(uint64 index)` Returns details of a specific withdrawal. **Parameters**: - `index` - Position in queue (0-based) **Returns**: - Completion height - Delegator address - Amount --- #### `committedWithdrawAmount(uint blockHeight)` Returns total withdrawal amount committed up to a block height. **Parameters**: - `blockHeight` - Block number **Returns**: Total committed amount --- #### `nextDepositAmount()` Returns amount pending deposit to chain. **Returns**: Pending deposit in Wei --- #### `nextWithdrawalAmount()` Returns amount pending withdrawal from chain. **Returns**: Pending withdrawal in Wei --- #### `failedWithdrawCount()` Returns count of failed withdrawals. **Returns**: Number of failed withdrawals --- #### `failedWithdrawAmount()` Returns total amount in failed withdrawals. **Returns**: Failed withdrawal amount --- ## Write Functions ### Validator Configuration #### `setCommissionRate(uint32 commissionRate_)` Updates validator commission rate. **Who Can Call**: Operator only **Parameters**: - `commissionRate_` - New rate (parts per million) **Constraints**: Must be ≤ protocol maximum --- #### `setWithdrawalFeeInGwei(uint96 withdrawalFeeInGwei_)` Updates withdrawal fee. **Who Can Call**: Operator only **Parameters**: - `withdrawalFeeInGwei_` - New fee in Gwei **Constraints**: Must be ≤ protocol maximum --- #### `setDescription(Description description_)` Updates validator description. **Who Can Call**: Operator only **Parameters**: - `description_` - New description struct --- ### Delegation Operations #### `delegate(address delegatorAddress)` Delegate tokens to this validator. **Who Can Call**: Anyone **Parameters**: - `delegatorAddress` - Address to credit with shares **Payment Required**: Yes (minimum 1 Gwei) **Example**: ```solidity validator.delegate{value: 100 ether}(msg.sender); ``` --- #### `undelegate(address withdrawalAddress, uint shares)` Undelegate tokens from validator. **Who Can Call**: Anyone with shares **Parameters**: - `withdrawalAddress` - Address to receive tokens - `shares` - Number of shares to undelegate **Payment Required**: Yes (must pay withdrawal fee) **Constraints**: - Must own enough shares - Operator must maintain minimum self-delegation - Tokens released after withdrawal delay **Example**: ```solidity uint96 fee = validator.withdrawalFeeInGwei(); validator.undelegate{value: fee * 1 gwei}(recipient, shares); ``` --- ### Earnings Management #### `withdrawCommission(address withdrawalAddress)` Withdraw accumulated commission. **Who Can Call**: Operator only **Parameters**: - `withdrawalAddress` - Address to receive commission **Constraints**: - Must have ≥1 Gwei commission - Goes to withdrawal queue (not instant) --- #### `withdrawTipFee(address withdrawalAddress)` Withdraw accumulated tip fees. **Who Can Call**: Operator only **Parameters**: - `withdrawalAddress` - Address to receive tips **Constraints**: - Only withdraws excess balance - Immediate transfer (not queued) --- ### System Operations #### `distributeRewards()` Distribute rewards to delegators and commission to operator. **Who Can Call**: Anyone (called by system) **Process**: 1. Community tax deducted 2. Commission calculated 3. Remaining distributed to delegators --- #### `processWithdrawQueue()` Process pending withdrawals that are ready. **Who Can Call**: Anyone **When**: After withdrawal delay period **Process**: - Checks ready withdrawals - Transfers funds - Failed transfers go to failed stack --- #### `processFailedWithdrawStack()` Retry failed withdrawals. **Who Can Call**: Anyone **Process**: - Retries all failed withdrawals - Still-failed amounts sent to community pool --- ## Common Use Cases ### For Delegators **Before Delegating:** ```solidity // Check validator settings uint32 commission = validator.commissionRate(); uint96 withdrawalFee = validator.withdrawalFeeInGwei(); uint bondStatus = validator.bondStatus(); // Should be 1 (Bonded) uint apy = validator.annualPercentageYield(); ``` **Delegate Tokens:** ```solidity validator.delegate{value: amount}(yourAddress); ``` **Check Your Delegation:** ```solidity (, uint shares) = validator.getDelegation(yourAddress); uint tokens = validator.convertToTokens(shares); ``` **Undelegate:** ```solidity uint96 fee = validator.withdrawalFeeInGwei(); validator.undelegate{value: fee * 1 gwei}(withdrawalAddress, shares); // Wait for withdrawal delay, then call processWithdrawQueue() ``` --- ### For Validator Operators **Update Settings:** ```solidity validator.setCommissionRate(50000); // 5% validator.setWithdrawalFeeInGwei(1); // 1 Gwei ``` **Check Earnings:** ```solidity uint commissionAmount = validator.commission(); uint tipFeeAmount = validator.tipFee(); ``` **Withdraw Earnings:** ```solidity // Withdraw commission (queued) validator.withdrawCommission(yourAddress); // Withdraw tips (immediate) validator.withdrawTipFee(yourAddress); ``` **Monitor Status:** ```solidity uint totalDelegated = validator.tokens(); uint activeStake = validator.stakes(); uint pendingWithdrawals = validator.withdrawCount(); ``` --- ## Important Notes :::warning **Key Constraints** - **Withdrawal Delays**: Undelegations enter a queue with delay period - **Minimum Amounts**: Most operations require ≥1 Gwei - **Fee Requirements**: Undelegation requires prepaid withdrawal fee - **Self-Delegation**: Operators must maintain minimum or lose commission ::: :::tip **Best Practices** - Always check `bondStatus()` before delegating - Use `convertToTokens()` to calculate delegation value - Monitor `failedWithdrawCount()` and process if needed - Operators should regularly claim commission and tips ::: --- ## Related Documentation - **[Validator Initialization](./staking-interfaces#validator-initialization)** - Set up a new validator - **[Staking Interfaces](./staking-interfaces)** - Full staking system guide - **[Run Validator Node](../../../run-a-node/validator-node)** - Node setup guide --- Need help? Join our [Discord](https://discord.gg/0glabs) for support. --- ## Technical Deep Dive Source: https://docs.0g.ai/developer-hub/building-on-0g/da-deep-dive.md The Data Availability (DA) module allows users to submit a piece of data, referred to as a **DA blob**. This data is redundantly encoded by the client's proxy and divided into several slices, which are then sent to DA nodes. **DA nodes** gain eligibility to verify the correctness of DA slices by staking. Each DA node verifies the integrity and correctness of its slice and signs it. Once more than 2/3 of the aggregated signatures are on-chain, the data behind the related hash is considered to be published decentrally. To incentivize DA nodes to store the signed data for a period, the signing process itself does not provide any rewards. Instead, rewards are distributed through a process called **DA Sampling**. During each DA Sample round, any DA slice within a certain timeframe can generate a lottery chance for a reward. DA nodes must store the corresponding slice to redeem the lottery chance and claim the reward. The process of generating DA nodes is the same as the underlying chain's PoS process, both achieved through staking. During each DA epoch (approximately 8 hours), DA nodes are assigned to several quorums. Within each quorum, nodes are assigned numbers 0 through 3071. Each number is assigned to exactly one node, but a node may be assigned to multiple quorums, depending on its staking weight. ## DA Processing Flow DA takes an input of data up to 32,505,852 bytes in length and processes it as follows: 1. **Padding and Size Encoding:** - Pad the data with zeros until it reaches 32,505,852 bytes - Add a little-endian format 4-byte integer at the end to indicate the original input size 2. **Matrix Formation:** - Slice the padded data into a 1024-row by 1024-column matrix, filling each row consecutively, with each element being 31 bytes - Pad each 31-byte element with an additional 1-byte zero, making it 32 bytes per element 3. **Redundant Encoding:** - Expand the data to a 3072-row by 1024-column matrix using redundancy coding - Calculate the **erasure commitment** and **data root** of the expanded matrix 4. **Submission to DA Contract:** - Submit the erasure commitment and data root to **the DA contract** and pay the fee - The DA contract will determine the epoch to which the data belongs and assign a quorum 5. **Data Distribution:** - Send the erasure commitment, data root, each row of the matrix, and necessary proofs of correctness to the corresponding DA nodes 6. **Signature Aggregation:** - More than 2/3 of the DA nodes sign the erasure commitment and data root - Aggregate the signatures using the BLS signature algorithm and submit the aggregated signature to the DA contract ### Details of Erasure Encoding After matrix formation, each element is processed into a 32-byte data unit, which can be viewed interchangeably as either 32 bytes of data or a 256-bit little-endian integer. Denote the element in the $i$-th row and $j$-th column as $c_{i,j}$. Let the finite field $\mathbb{F}$ be the scalar field of the [BN254 curve](https://docs.rs/ark-bn254/latest/ark_bn254/). Each element $c_{i,j}$ is also considered an integer within the finite field $\mathbb{F}$. Let $p$ be the order of $\mathbb{F}$, a known large number that can be expressed as $2^{28} \times A + 1$, where $A$ is an odd number. The number 3 is a generator of the multiplicative group of the $\mathbb{F}$. Define $u = 3^{2^6 \times A}$ and $w=3^{2^8\times A}$, so $w^{2^{20}} = 1$ and $u^4=w$. Now we define a polynomial $f$ over $\mathbb{F}\rightarrow\mathbb{F}$ with degree $d=2^{20}-1$ satisfying $\forall\, 0\le i< 1024,\, 0\le j< 1024,\,f\left(w^{1024j+i}\right)=c_{i,j}$ Then we extend the $1024\times1024$ matrix into $1024\times 3072$ matrix, where $\forall\, 1024\le i< 2048,\, 0\le j< 1024,\,c_{i,j}=f\left(u^2\cdot w^{1024j+(i-1024)}\right)$ $\forall\, 2048\le i< 3072,\, 0\le j< 1024,\,c_{i,j}=f\left(u\cdot w^{1024j+(i-2048)}\right)$ The **erasure commitment** is the KZG commitment of $f$, defined as $f(\tau)\cdot G$, where $G$ is the starting point of BN254 G1 curve, and $\tau$ is a latent parameter from the [perpetual powers of tau trusted setup ceremony](https://github.com/privacy-scaling-explorations/perpetualpowersoftau). The **data root** is defined as the input root by treating the 1024\*3072 32-byte elements as a continuous storage submission input. Specifically, according to the storage submission requirements, these data does not need to pad any zeros, and will be divided into a 16384-element sector array and an 8192-element sector array. DA nodes need to verify two parts: 1. The consistency between the received slice and the data root, mainly achieved through Merkle proofs 2. The consistency between the received slice and the erasure commitment, verified using KZG proofs. Here, we use the AMT protocol optimization introduced in [LVMT](https://www.usenix.org/system/files/osdi23-li-chenxing.pdf) to reduce the proving overhead ## DA Sampling The blockchain will periodically release DA Sampling tasks at preset height every `SAMPLE_PERIOD` blocks, with the parent block hash of these heights used as the `sampleSeed` for DA Sampling. ### List of Parameters **Constant parameters** | Parameter | Requirement | Default value | |-----------|-------------|---------------| | MAX_PODAS_TARGET | | 2^256 / 128 - 1 | **Admin adjustable parameters** | Parameter | Requirement | Default value | Code | |-----------|-------------|---------------|------| | TARGET_SUBMITS | | 20 | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L296) | | EPOCH_WINDOW_SIZE | | 300 (about 3 months) | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L306) | | SAMPLE_PERIOD | | 30 (about 1.5 minutes) | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L323) | ### Responses During each period, each DA slice (one row) can be divided into 32 sub-lines. For each sub-line, the `podasQuality` will be computed using the `dataRoot` and assigned `epoch` and `quorumId` of its corresponding DA blob. :::note By default, all integers are in 256-bit big-endian format when computing hash values. `lineIndex` is the only exception, which is in 64-bit big-endian format. ::: The hash value can be viewed interchangeably as either 32 bytes of data or a 256-bit big-endian integer. ```python lineQuality = keccak256(sampleSeed, epoch, quorumId, dataRoot, lineIndex); dataQuality = keccak256(lineQuality, sublineIndex, data); podasQuality = lineQuality + dataQuality ``` If the `podasQuality` is less than the current `podasTarget` in the DA contract and the `epoch` falls within `[currentEpoch - EPOCH_WINDOW_SIZE, currentEpoch)`, then this sub-line is regarded as a **valid DAS response** and is eligible for the reward. The DA node assigned to this row can claim the reward. During a sample period, at most `TARGET_SUBMITS × 2` DAS responses can be submitted and rewarded; any submissions exceeding this limit will be rejected. ### Difficulty Adjustment `TARGET_SUBMITS` valid responses are expected in a sample period. If more or fewer responses are submitted during a sample period, the `podasTarget` will be adjusted as follows: ```python podasTarget -= podasTarget * (actualSubmits - TARGET_SUBMITS) / TARGET_SUBMITS / 8 ``` ## Economic Model ### List of Parameters **Admin adjustable parameters** | Parameter | Requirement | Default value | Code | |-----------|-------------|---------------|------| | BASE_REWARD | | 0 | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L318) | | BLOB_PRICE | | 0 | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L331) | | SERVICE_FEE_RATE_BP | | 0 | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L336) | | REWARD_RATIO | [1] | 1,200,000 | [Link](https://github.com/0gfoundation/0g-da-contract/blob/3951565fb6ad3096634da6493e9e863bb2846611/contracts/DAEntrance.sol#L312) | [1] `TARGET_SUBMITS` × Time elapsed for `EPOCH_WINDOW_SIZE` epochs / Time elapsed in `SAMPLE_PERIOD` / `REWARD_RATIO` should be approximately 0.5 to 2. ### Pricing When users submit the metadata for a DA blob, they need to pay a fee in amount of `BLOB_PRICE`. ### Reward When a DA epoch ends, all the rewards from that DA epoch will be stored in the DA reward pool. Each time a valid response is submitted, `1 / REWARD_RATIO` of the reward pool will be distributed to the corresponding DA node. ### System Rewards In the early stages of the ecosystem, the foundation can reserve a portion of tokens for system rewards. When the DA node submits a valid response, an additional reward of `BASE_REWARD` will be issued. The funds for the base reward will be manually deposited into the reward contract and tracked separately. If the balance for the base reward is insufficient to cover a single base reward, miners will not be able to receive the full base reward. ### Service Fee A system service fee is charged as a proportion of the DA fees paid by the user, according to the parameter `SERVICE_FEE_RATE_BP`. ## Run a Node See [here](/run-a-node/da-node) for instructions to become DA signer and run your own node. --- *Ready to dive deeper into 0G DA? Join our [Discord](https://discord.gg/0glabs) for technical discussions.* --- ## DA Client Nodes Source: https://docs.0g.ai/developer-hub/building-on-0g/da-integration.md To submit data to the 0G DA, you must run a DA Client node and the Encoder node. The DA client interfaces with the Encoder for data encoding and the Retriever for data access. ## Overview ### Maximum Blob Size Users can submit data blobs up to 32,505,852 bytes in length, which are then processed, encoded, and distributed across a network of DA nodes. The system employs a sophisticated data processing flow that includes padding, matrix formation, redundant encoding, and signature aggregation. ### Fee Market As the DA user, you pay a fee which is the (BLOB_PRICE) when submitting DA blob data. ### Submitting Data See example here: https://github.com/0gfoundation/0g-da-example-rust/blob/main/src/disperser.proto ## Hardware Requirements The following table outlines the hardware requirements for different types of DA Client nodes: | Node Type | Memory | CPU | Disk | Bandwidth | Additional Notes | |-----------|--------|-----|------|-----------|------------------| | DA Client | 8 GB | 2 cores | - | 100 MBps | For Download / Upload | | DA Encoder | - | - | - | - | NVIDIA Drivers: 12.04 on the RTX 4090* | | DA Retriever | 8 GB | 2 cores | - | 100 MBps | For Download / Upload | ## Standing up DA Client, Encoder, Retriever ## DA Client Node Installation **1. Clone the DA Client Node Repo** ```bash git clone https://github.com/0gfoundation/0g-da-client.git ``` **2. Build the Docker Image** ```bash cd 0g-da-client docker build -t 0g-da-client -f combined.Dockerfile . ``` **3. Set Environment Variables** Create a file named `envfile.env` with the following content. Be sure you paste in your private key. ```bash # envfile.env COMBINED_SERVER_CHAIN_RPC=https://evmrpc-testnet.0g.ai COMBINED_SERVER_PRIVATE_KEY=YOUR_PRIVATE_KEY ENTRANCE_CONTRACT_ADDR=0x857C0A28A8634614BB2C96039Cf4a20AFF709Aa9 COMBINED_SERVER_RECEIPT_POLLING_ROUNDS=180 COMBINED_SERVER_RECEIPT_POLLING_INTERVAL=1s COMBINED_SERVER_TX_GAS_LIMIT=2000000 COMBINED_SERVER_USE_MEMORY_DB=true COMBINED_SERVER_KV_DB_PATH=/runtime/ COMBINED_SERVER_TimeToExpire=2592000 DISPERSER_SERVER_GRPC_PORT=51001 BATCHER_DASIGNERS_CONTRACT_ADDRESS=0x0000000000000000000000000000000000001000 BATCHER_FINALIZER_INTERVAL=20s BATCHER_CONFIRMER_NUM=3 BATCHER_MAX_NUM_RETRIES_PER_BLOB=3 BATCHER_FINALIZED_BLOCK_COUNT=50 BATCHER_BATCH_SIZE_LIMIT=500 BATCHER_ENCODING_INTERVAL=3s BATCHER_ENCODING_REQUEST_QUEUE_SIZE=1 BATCHER_PULL_INTERVAL=10s BATCHER_SIGNING_INTERVAL=3s BATCHER_SIGNED_PULL_INTERVAL=20s BATCHER_EXPIRATION_POLL_INTERVAL=3600 BATCHER_ENCODER_ADDRESS=DA_ENCODER_SERVER BATCHER_ENCODING_TIMEOUT=300s BATCHER_SIGNING_TIMEOUT=60s BATCHER_CHAIN_READ_TIMEOUT=12s BATCHER_CHAIN_WRITE_TIMEOUT=13s ``` **4. Run the Docker Node** ```bash docker run -d --env-file envfile.env --name 0g-da-client -v ./run:/runtime -p 51001:51001 0g-da-client combined ``` ## Configuration | Field | Description | |-------|-------------| | `--chain.rpc` | JSON RPC node endpoint for the blockchain network. | | `--chain.private-key` | Hex-encoded signer private key. | | `--chain.receipt-wait-rounds` | Maximum retries to wait for transaction receipt. | | `--chain.receipt-wait-interval` | Interval between retries when waiting for transaction receipt. | | `--chain.gas-limit` | Transaction gas limit. | | `--combined-server.use-memory-db` | Whether to use mem-db for blob storage. | | `--combined-server.storage.kv-db-path` | Path for level db. | | `--combined-server.storage.time-to-expire` | Expiration duration for blobs in level db. | | `--combined-server.log.level-file` | File log level. | | `--combined-server.log.level-std` | Standard output log level. | | `--combined-server.log.path` | Log file path. | | `--disperser-server.grpc-port` | Server listening port. | | `--disperser-server.retriever-address` | GRPC host for retriever. | | `--batcher.da-entrance-contract` | Hex-encoded da-entrance contract address. | | `--batcher.da-signers-contract` | Hex-encoded da-signers contract address. | | `--batcher.finalizer-interval` | Interval for finalizing operations. | | `--batcher.finalized-block-count` | Default number of blocks between finalized block and latest block. | | `--batcher.confirmer-num` | Number of Confirmer threads. | | `--batcher.max-num-retries-for-sign` | Number of retries before signing fails. | | `--batcher.batch-size-limit` | Maximum batch size in MiB. | | `--batcher.encoding-request-queue-size` | Size of the encoding request queue. | | `--batcher.encoding-interval` | Interval between blob encoding requests. | | `--batcher.pull-interval` | Interval for pulling from the encoded queue. | | `--batcher.signing-interval` | Interval between slice signing requests. | | `--batcher.signed-pull-interval` | Interval for pulling from the signed queue. | | `--encoder-socket` | GRPC host of the encoder. | | `--encoding-timeout` | Total time to wait for a response from encoder. | | `--signing-timeout` | Total time to wait for a response from signer. | ## Features - `parallel`: Uses parallel algorithms for computations, maximizing CPU resource utilization. - `cuda`: Uses GPU for computations, applicable only on platforms with NVIDIA GPUs. :::note GPU support is currently tested with NVIDIA 12.04 drivers on the RTX 4090. Other NVIDIA GPUs may require parameter adjustments and have not been tuned yet. ::: ## Preparation ### Install Rust Ensure you have curl installed. Run the following command to install Rust: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` After installation, add the cargo bin directory to your PATH environment variable: ```bash source $HOME/.cargo/env ``` Verify the installation: ```bash rustc --version ``` ### Install other dependencies ```bash # Install Protocol Buffers Compiler sudo apt-get install -y protobuf-compiler # Install a specific nightly Rust toolchain and rustfmt rustup toolchain install nightly-2024-02-04-x86_64-unknown-linux-gnu rustup component add --toolchain nightly-2024-02-04-x86_64-unknown-linux-gnu rustfmt # Add the necessary Rust target rustup target add x86_64-unknown-linux-gnu ``` ### Install CUDA (for GPU feature) Ensure you have an NVIDIA GPU with the required drivers. Then follow the instructions from [CUDA Toolkit](https://developer.nvidia.com/cuda-toolkit). Verify the installation: ```bash nvidia-smi nvcc --version ``` ## Building Public Parameters The public parameters for the cryptographic protocol are built in two steps: ### 1. Download and process the perpetual power of tau We use the challenge_0084 file from the nearly most recent submission. ```bash curl https://pse-trusted-setup-ppot.s3.eu-central-1.amazonaws.com/challenge_0084 -o challenge_0084 ``` ### 2. Build the AMT parameters You can either construct these parameters yourself or download pre-built files. #### Choice 1: Download the pre-built files ```bash ./dev-support/download_params.sh ``` #### Choice 2: Construct the parameters yourself ```bash ./dev_support/build_params.sh challenge_0084 ``` ## Running the Server Run the server with the following command: ```bash cargo run -r -p server --features grpc/parallel,grpc/cuda -- --config run/config.toml ``` :::note If you do not have a CUDA environment, remove the cuda feature. ::: DA Encoder will serve on port 34000 with the specified gRPC interface. ## Using the Verification Logic Add the following to `Cargo.toml` of your crate: ```toml zg-encoder = { git = "https://github.com/0gfoundation/0g-da-encoder.git" } ``` Use the `zg_encoder::EncodedSlice::verify` function for verifying. ## Benchmark the Performance Run the following task: ```bash cargo bench -p grpc --features grpc/parallel,grpc/cuda --bench process_data --features zg-encoder/production_mode -- --nocapture ``` ## Development and Testing Run the following script for complete testing: ```bash ./dev_support/test.sh ``` ## DA Retriever Node Installation **1. Clone the DA Retriever Node Repo** ```bash git clone https://github.com/0gfoundation/0g-da-retriever.git cd 0g-da-retriever ``` **2. Edit Files** Add the following line to Dockerfile.dockerignore file: ```bash !/run/config.toml ``` Replace Dockerfile with the following: ```dockerfile # Dockerfile FROM rust:alpine3.20 as builder WORKDIR /0g-da-retriever COPY . . RUN apk update && apk add --no-cache make protobuf-dev musl-dev RUN cargo build --release FROM alpine:3.20 WORKDIR /0g-da-retriever COPY --from=builder /0g-da-retriever/target/release/retriever /usr/local/bin/retriever # Copy the config file into the container COPY --from=builder /0g-da-retriever/run/config.toml ./run/config.toml # Set the entrypoint to run the retriever binary CMD ["/usr/local/bin/retriever"] ``` Replace the Config impl in `/retriever/src/config.rs` with the following: ```rust impl Config { pub fn from_cli_file() -> Result { let matches = cli::cli_app().get_matches(); let config_file = matches .get_one::("config") .map(|s| s.as_str()) .unwrap_or("/0g-da-retriever/run/config.toml"); let c = RawConfig( config::Config::builder() .add_source(config::File::with_name(config_file)) .build()?, ); Ok(Self { log_level: c.get_string("log_level")?, eth_rpc_url: c.get_string("eth_rpc_endpoint")?, grpc_listen_address: c.get_string("grpc_listen_address")?, max_ongoing_retrieve_request: c.get_u64_opt("max_ongoing_retrieve_request")?, }) } } ``` **3. Update Configuration** Update configuration file `run/config.toml` as needed with context below. | Field | Description | |-------|-------------| | log_level | Set log level. | | grpc_listen_address | Server listening address. | | eth_rpc_endpoint | JSON RPC node endpoint for the blockchain network. | **4. Build and Run the Docker Node** ```bash docker build -t 0g-da-retriever . docker run -d --name 0g-da-retriever -p 34005:34005 0g-da-retriever ``` ## Troubleshooting
DA Client connection issues - Verify the RPC endpoint is accessible - Check that your private key has sufficient funds for gas - Ensure the contract addresses are correct for your network - Review logs: `docker logs 0g-da-client`
Encoder GPU not detected - Verify NVIDIA drivers are installed: `nvidia-smi` - Check CUDA installation: `nvcc --version` - Ensure Docker has GPU access if using containers - Try running without cuda feature if GPU is not available
Retriever fails to start - Check that port 34005 is not already in use - Verify the Ethereum RPC endpoint is accessible - Ensure config.toml is properly formatted - Review container logs for specific errors
## Next Steps - **Integration Examples** → [DA Examples Repository](https://github.com/0gfoundation/0g-da-example-rust) - **Join Community** → [Discord](https://discord.gg/0glabs) for support - **Run a DA Node** → [DA Node Guide](/run-a-node/da-node) --- *Ready to integrate 0G DA into your application? Start with the DA Client and connect to the network.* --- ## Goldsky Subgraphs Source: https://docs.0g.ai/developer-hub/building-on-0g/indexing/goldsky.md Goldsky is Web3's real-time data platform, giving developers the fastest way to query, stream, and scale onchain data without worrying about maintaining infrastructure. With resilient subgraphs and flexible data streaming pipelines, you can focus on building great user experiences while Goldsky handles the heavy lifting of indexing. ## Why Goldsky? - **Reliable Performance**: Scalable infra built to handle data challenges as your app grows. - **Intuitive Tools**: Easily integrate without being slowed down by complex data engineering. - **24/7 Support**: Goldsky offers [support](https://docs.goldsky.com/getting-support) when you need to fix bugs or optimize deployments. --- ## Goldsky Products ### Subgraphs **Subgraphs** make blockchain data queryable with GraphQL endpoints so you can easily fetch specifically only the data your app needs. - **Fast Queries**: Optimized for low latency and high throughput. - **Customizable**: Tailor indexing logic to your app's exact needs. - **Organized & Scalable**: Tagging and versioning keep data clean as your project grows. **Typical Use Cases**: dApps, NFT marketplaces, gaming, DAOs, or any app needing reliable onchain data. ### Mirror **Mirror** streams decoded blockchain data directly into your database so you can own your data and have full control over what to do with it. - **Realtime Streaming**: Stream onchain activity straight into your existing systems. - **Combine Data Sources**: Access data across multiple chains and join it with your own offchain data. - **Continuously Synced**: Automatic updates keep everything accurate and fresh. **Typical Use Cases**: Advanced analytics, loyalty programs, points/leaderboards, user progress tracking, custom dashboards, or app requiring rich onchain data joined with other datasets. --- ## Getting Started Check out the [Goldsky docs](https://docs.goldsky.com/chains/0g) to start indexing today. Build smarter, scale faster, and deliver seamless experiences to your users. --- ## Building on 0G Source: https://docs.0g.ai/developer-hub/building-on-0g/introduction.md Build AI-powered applications using 0G's modular infrastructure - with or without migrating your existing code. **Keep your current blockchain and add 0G services as needed.** Our infrastructure works with: - ✅ Any EVM chain (Ethereum, Polygon, BNB, Arbitrum) - ✅ Non-EVM chains (Solana, Near, Cosmos) - ✅ Traditional Web2 applications ## Prerequisites Before building: 1. **Get testnet tokens** from the [faucet](https://faucet.0g.ai) 2. **Install relevant SDK** for your language 3. **Review service documentation** for your chosen components ## What's Next? Based on your needs, dive into: - **Dapp Migration?** → [Deploy on 0G Chain](/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) - **Need Storage?** → [Storage SDK Guide](/developer-hub/building-on-0g/storage/sdk) - **Need Compute?** → [Compute Router](/developer-hub/building-on-0g/compute-network/router/overview) - **Building a Rollup?** → [DA Integration](/developer-hub/building-on-0g/da-integration) - **Creating Agentic IDs?** → [Agentic ID Overview](/developer-hub/building-on-0g/agentic-id/overview) --- 💡 **Pro Tip**: Start with one service, prove the value, then expand. Most successful projects begin with 0G Storage or Compute before exploring other services. --- ## Caldera on 0G DA Source: https://docs.0g.ai/developer-hub/building-on-0g/rollup-as-a-service/caldera-on-0g-da.md Under construction... --- ## Arbitrum Nitro on 0G DA Source: https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/arbitrum-nitro-on-0g-da.md Arbitrum Nitro is a high-performance Ethereum rollup that uses a new consensus mechanism called "Nitro" to achieve scalability and efficiency. 0G DA is a high-performance data availability layer that can be used for Arbitrum Nitro to provide a cost-effective and secure solution for storing transaction data. ## Overview ### DA Provider Implementation The Arbitrum Nitro code includes a `DataAvailabilityProvider` interface, which is utilized throughout the codebase for storing and retrieving data from various providers, including EIP-4844 blobs, Anytrust, and now 0G. This integration adds an implementation of the `DataAvailabilityProvider` interface specifically for 0G. The main functionality for posting and retrieving data is found in the `das/zerogravity.go` file, where the data is stored on 0G. ### GitHub Repository Find the repository for this integration at: https://github.com/0gfoundation/nitro ## Prerequisites Before setting up your Arbitrum Nitro rollup with 0G DA, ensure you have: - [0G DA Client Node](../da-integration.md) - [0G DA Encoder Node](../da-integration.md) - [0G Arbitrum Nitro Rollup Kit](https://github.com/0gfoundation/nitro) :::warning Beta Integration This is a beta integration and we are working on resolving open issues. Please check the repository for the latest updates and known issues. ::: ## Next Steps For detailed setup instructions and configuration: 1. **Set up DA infrastructure** → Follow the [DA integration guide](../da-integration.md) 2. **Clone the integration** → Visit the [0G Nitro repository](https://github.com/0gfoundation/nitro) 3. **Follow setup guide** → Check the repository README for specific deployment steps ## Support - **Technical Issues** → [GitHub Issues](https://github.com/0gfoundation/nitro/issues) - **Community Support** → [Discord](https://discord.gg/0glabs) --- *Stay tuned for more detailed documentation as this integration matures.* --- ## OP Stack on 0G DA Source: https://docs.0g.ai/developer-hub/building-on-0g/rollups-and-appchains/op-stack-on-0g-da.md Optimism is a lightning-fast Ethereum L2 blockchain, built with the OP Stack. 0G DA is a high-performance data availability layer that can be used with Optimism to provide a cost-effective and secure solution for storing transaction data. ## Overview To implement this server specification, 0G DA provides a `da-server` that runs as a sidecar process alongside the OP Stack rollup node. This server connects to a 0G DA client to securely communicate with the 0G DA network. ### Required Components - [0G DA client node](/developer-hub/building-on-0g/da-integration) - [0G DA encoder node](/developer-hub/building-on-0g/da-integration) - 0G DA Server (deployment guide below) - OP Stack components with configuration adjustments ### GitHub Repository Find the repository for this integration at: https://github.com/0gfoundation/0g-da-op-plasma The Optimism codebase has been extended to integrate with the 0G DA `da-server`. This server utilizes the 0G DA Open API to efficiently store and retrieve rollup data. ## Deployment Steps ### 1. Deploy DA Server **Build the Docker image:** ```bash docker build -t 0g-da-op-plasma . ``` **Run the Docker container:** Adjust commands and parameters as required for your setup: ```bash docker run -p 3100:3100 0g-da-op-plasma:latest da-server \ --addr 0.0.0.0 \ --port 3100 \ --zg.server rpc_to_a_da_client # default: 127.0.0.1:51001 ``` **Build DA Server:** ```bash git clone https://github.com/0gfoundation/0g-da-op-plasma.git cd 0g-da-op-plasma make da-server ``` **Run DA Server:** ```bash ./bin/da-server \ --addr 127.0.0.1 \ --port 3100 \ --zg.server rpc_to_a_da_client # default: 127.0.0.1:51001 ``` **DA Server Configuration Flags:** | Flag | Description | Default | |------|-------------|---------| | `--zg.server` | 0G DA client server endpoint | `localhost:51001` | | `--addr` | Server listening address | - | | `--port` | Server listening port | - | ### 2. Deploy DA Client and DA Encoder For guidance on setting up a 0G DA client and DA Encoder, refer to the [DA integration documentation](../da-integration.md). ### 3. Deploy OP Stack ## Prerequisites Ensure you have installed the following software: | Software | Version | |----------|---------| | Git | OS default | | Go | 1.21.6 | | Node | ^20 | | just | 1.34.0 | | Make | OS default | | jq | OS default | | direnv | Latest | **Required releases:** - op-node/v1.9.1 - op-proposer/v1.9.1 - op-batcher/v1.9.1 - op-geth v1.101408.0 ## Build the Optimism Monorepo **1. Clone and navigate to the Optimism Monorepo:** ```bash git clone https://github.com/ethereum-optimism/optimism.git cd optimism git fetch --tag --all git checkout v1.9.1 git submodule update --init --recursive ``` **2. Check your dependencies:** ```bash ./packages/contracts-bedrock/scripts/getting-started/versions.sh ``` **3. Compile the necessary packages:** ```bash make op-node op-batcher op-proposer make build ``` ## Build the Optimism Geth Source **1. Clone and navigate to op-geth:** ```bash git clone https://github.com/ethereum-optimism/op-geth.git cd op-geth git fetch --tag --all git checkout v1.101408.0 ``` **2. Compile op-geth:** ```bash make geth ``` ## Get Access to a Sepolia Node For deploying to Sepolia, access an L1 node using a provider like [Alchemy](https://www.alchemy.com/) (easier) or run your own Sepolia node (harder). ## Configure Environment Variables **1. Enter the Optimism Monorepo:** ```bash cd ~/optimism ``` **2. Duplicate the sample environment variable file:** ```bash cp .envrc.example .envrc ``` **3. Fill out the environment variables:** | Variable Name | Description | |---------------|-------------| | `L1_RPC_URL` | URL for your L1 node (a Sepolia node in this case) | | `L1_RPC_KIND` | Kind of L1 RPC you're connecting to (`alchemy`, `quicknode`, `infura`, `parity`, `nethermind`, `debug_geth`, `erigon`, `basic`, `any`) | ## Generate Addresses You'll need four addresses and their private keys: - **Admin**: Has the ability to upgrade contracts - **Batcher**: Publishes Sequencer transaction data to L1 - **Proposer**: Publishes L2 transaction results (state roots) to L1 - **Sequencer**: Signs blocks on the p2p network **1. Navigate to the contracts-bedrock package:** ```bash cd ~/optimism/packages/contracts-bedrock ``` **2. Generate accounts:** ```bash ./scripts/getting-started/wallets.sh ``` you will get the following output: ```bash Copy the following into your .envrc file: # Admin address export GS_ADMIN_ADDRESS=0x9625B9aF7C42b4Ab7f2C437dbc4ee749d52E19FC export GS_ADMIN_PRIVATE_KEY=0xbb93a75f64c57c6f464fd259ea37c2d4694110df57b2e293db8226a502b30a34 # Batcher address export GS_BATCHER_ADDRESS=0xa1AEF4C07AB21E39c37F05466b872094edcf9cB1 export GS_BATCHER_PRIVATE_KEY=0xe4d9cd91a3e53853b7ea0dad275efdb5173666720b1100866fb2d89757ca9c5a # Proposer address export GS_PROPOSER_ADDRESS=0x40E805e252D0Ee3D587b68736544dEfB419F351b export GS_PROPOSER_PRIVATE_KEY=0x2d1f265683ebe37d960c67df03a378f79a7859038c6d634a61e40776d561f8a2 # Sequencer address export GS_SEQUENCER_ADDRESS=0xC06566E8Ec6cF81B4B26376880dB620d83d50Dfb export GS_SEQUENCER_PRIVATE_KEY=0x2a0290473f3838dbd083a5e17783e3cc33c905539c0121f9c76614dda8a38dca ``` **3. Save the addresses:** Copy the output from the above command and paste it into your `.envrc` file. Fund the addresses with Sepolia ETH: - Admin: 0.5 ETH - Proposer: 0.2 ETH - Batcher: 0.1 ETH :::warning Production Note Use secure hardware for key management in production environments. cast wallet is not designed for production deployments. ::: ## Load Environment Variables **1. Enter the Optimism Monorepo:** ```bash cd ~/optimism ``` **2. Load the variables with direnv:** ```bash direnv allow ``` ## Deploy Core Contracts **1. Update the deployment configuration:** ```bash cd packages/contracts-bedrock ./scripts/getting-started/config.sh ``` **2. Add 0G DA configuration:** Add the following at the bottom of `getting_started.json`: ```json { "useAltDA": true, "daCommitmentType": "GenericCommitment", "daChallengeWindow": 160, "daResolveWindow": 160, "daBondSize": 1000000, "daResolverRefundPercentage": 0 } ``` **3. Deploy contracts (this can take up to 15 minutes):** ```bash DEPLOYMENT_OUTFILE=deployments/artifact.json \ DEPLOY_CONFIG_PATH=deploy-config/getting-started.json \ forge script scripts/deploy/Deploy.s.sol:Deploy \ --broadcast --private-key $GS_ADMIN_PRIVATE_KEY \ --rpc-url $L1_RPC_URL --slow ``` **4. Generate L2 allocations:** ```bash CONTRACT_ADDRESSES_PATH=deployments/artifact.json \ DEPLOY_CONFIG_PATH=deploy-config/getting-started.json \ STATE_DUMP_PATH=deploy-config/statedump.json \ forge script scripts/L2Genesis.s.sol:L2Genesis \ --sig 'runWithStateDump()' --chain ``` ## Set Up L2 Configuration **1. Navigate to the op-node directory:** ```bash cd ~/optimism/op-node ``` **2. Generate genesis and rollup configuration:** ```bash go run cmd/main.go genesis l2 \ --deploy-config ../packages/contracts-bedrock/deploy-config/getting-started.json \ --l1-deployments ../packages/contracts-bedrock/deployments/artifact.json \ --outfile.l2 genesis.json \ --outfile.rollup rollup.json \ --l1-rpc $L1_RPC_URL \ --l2-allocs ../packages/contracts-bedrock/deploy-config/statedump.json ``` **3. Add alt_da configuration to rollup.json:** ```json { "alt_da": { "da_challenge_contract_address": "0x0000000000000000000000000000000000000000", "da_commitment_type": "GenericCommitment", "da_challenge_window": 160, "da_resolve_window": 160 } } ``` **4. Generate JWT secret:** ```bash openssl rand -hex 32 > jwt.txt ``` **5. Copy files to op-geth directory:** ```bash cp genesis.json ~/op-geth cp jwt.txt ~/op-geth ``` ## Initialize and Run Components ### Initialize op-geth ```bash cd ~/op-geth mkdir datadir build/bin/geth init --datadir=datadir genesis.json ``` ### Run op-geth ```bash cd ~/op-geth ./build/bin/geth \ --datadir ./datadir \ --http \ --http.corsdomain="*" \ --http.vhosts="*" \ --http.addr=0.0.0.0 \ --http.port=9545 \ --http.api=web3,debug,eth,txpool,net,engine \ --ws \ --ws.addr=0.0.0.0 \ --ws.port=9546 \ --ws.origins="*" \ --ws.api=debug,eth,txpool,net,engine \ --syncmode=full \ --nodiscover \ --maxpeers=0 \ --networkid=42069 \ --authrpc.vhosts="*" \ --authrpc.addr=0.0.0.0 \ --authrpc.port=9551 \ --authrpc.jwtsecret=./jwt.txt \ --rollup.disabletxpoolgossip=true \ --state.scheme=hash ``` ### Run op-node ```bash cd ~/optimism/op-node ./bin/op-node \ --l2=http://localhost:9551 \ --l2.jwt-secret=./jwt.txt \ --sequencer.enabled \ --sequencer.l1-confs=5 \ --verifier.l1-confs=4 \ --rollup.config=./rollup.json \ --rpc.addr=0.0.0.0 \ --rpc.port=8547 \ --p2p.disable \ --rpc.enable-admin \ --p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY \ --l1=$L1_RPC_URL \ --l1.rpckind=$L1_RPC_KIND \ --altda.enabled=true \ --altda.da-server= \ --altda.da-service=true \ --l1.beacon.ignore=true ``` ### Run op-batcher ```bash cd ~/optimism/op-batcher ./bin/op-batcher \ --l2-eth-rpc=http://localhost:9545 \ --rollup-rpc=http://localhost:8547 \ --poll-interval=1s \ --sub-safety-margin=6 \ --num-confirmations=1 \ --safe-abort-nonce-too-low-count=3 \ --resubmission-timeout=30s \ --rpc.addr=0.0.0.0 \ --rpc.port=8548 \ --rpc.enable-admin \ --max-channel-duration=1 \ --l1-eth-rpc=$L1_RPC_URL \ --private-key=$GS_BATCHER_PRIVATE_KEY \ --altda.enabled=true \ --altda.da-service=true \ --altda.da-server= ``` :::tip Controlling Batcher Costs The `--max-channel-duration=n` setting controls how often data is written to L1. Lower values mean faster synchronization but higher costs. Set to 0 to disable or increase for lower costs. ::: ### Run op-proposer ```bash cd ~/optimism/op-proposer ./bin/op-proposer \ --poll-interval=12s \ --rpc.port=9560 \ --rollup-rpc=http://localhost:8547 \ --l2oo-address=$L2OO_ADDR \ --private-key=$GS_PROPOSER_PRIVATE_KEY \ --l1-eth-rpc=$L1_RPC_URL ``` ## Acquire Sepolia ETH for Layer 2 **1. Navigate to contracts-bedrock:** ```bash cd ~/optimism/packages/contracts-bedrock ``` **2. Find the L1 standard bridge contract address:** ```bash cat deployments/artifact.json | jq -r .L1StandardBridgeProxy ``` **3. Send Sepolia ETH to the bridge contract address** ## Test Your Rollup You now have a fully operational 0G DA-powered Optimism-based EVM Rollup. Experiment with it as you would with any other test blockchain. :::important Notes - This is a beta integration with active development ongoing - Ensure all necessary ports are open in your firewall configuration - Refer to the [Optimism documentation](https://docs.optimism.io/) for additional configuration options and troubleshooting ::: --- *Congratulations on setting up your OP Stack rollup with 0G DA!* --- ## Storage SDK Source: https://docs.0g.ai/developer-hub/building-on-0g/storage/sdk.md Build decentralized storage into your applications with our powerful SDKs designed for modern development workflows. ## Available SDKs - **Go SDK**: Ideal for backend systems and applications built with Go - **TypeScript SDK**: Perfect for frontend development and JavaScript-based projects ## Core Features Both SDKs provide a streamlined interface to interact with the 0G Storage network: - **Upload and Download Files**: Securely store and retrieve data of various sizes and formats - **Manage Data**: List uploaded files, check their status, and control access permissions - **Leverage Decentralization**: Benefit from the 0G network's distributed architecture for enhanced data availability, immutability, and censorship resistance ## Quick Start Resources :::tip Starter Kits Available Get up and running quickly with our starter kits: - **[TypeScript Starter Kit](https://github.com/0gfoundation/0g-storage-ts-starter-kit)** - CLI scripts, importable library, and browser UI with MetaMask wallet connect. Supports turbo/standard modes. - **[Go Starter Kit](https://github.com/0gfoundation/0g-storage-go-starter-kit)** - Ready-to-use examples with Gin server and CLI tool ```bash # TypeScript — upload a file in under 5 minutes git clone https://github.com/0gfoundation/0g-storage-ts-starter-kit cd 0g-storage-ts-starter-kit && npm install cp .env.example .env # Add your PRIVATE_KEY npm run upload -- ./file.txt ``` ::: ## Installation Install the 0G Storage Client library: ```bash go get github.com/0gfoundation/0g-storage-client ``` ## Setup ### Import Required Packages ```go import ( "context" "github.com/0gfoundation/0g-storage-client/common/blockchain" "github.com/0gfoundation/0g-storage-client/common" "github.com/0gfoundation/0g-storage-client/indexer" "github.com/0gfoundation/0g-storage-client/transfer" "github.com/0gfoundation/0g-storage-client/core" ) ``` ### Initialize Clients Create the necessary clients to interact with the network: ```go // Create Web3 client for blockchain interactions w3client := blockchain.MustNewWeb3(evmRpc, privateKey) defer w3client.Close() // Create indexer client for node management indexerClient, err := indexer.NewClient(indRpc, indexer.IndexerClientOption{ LogOption: common.LogOption{}, }) if err != nil { // Handle error } ``` **Parameters:** `evmRpc` is the chain RPC endpoint, `privateKey` is your signer key, and `indRpc` is the indexer RPC endpoint. Use the current values published in the network overview docs for your network. ## Core Operations ### Node Selection Select storage nodes before performing file operations: ```go nodes, err := indexerClient.SelectNodes(ctx, expectedReplicas, droppedNodes, method, fullTrusted) if err != nil { // Handle error } ``` **Parameters:** `ctx` is the context for the operation. `expectedReplicas` is the number of replicas to maintain. `droppedNodes` is a list of nodes to exclude, `method` can be `min`, `max`, `random`, or a positive number string, and `fullTrusted` limits selection to trusted nodes. ### File Upload Upload files to the network with the indexer client: ```go file, err := core.Open(filePath) if err != nil { // Handle error } defer file.Close() fragmentSize := int64(4 * 1024 * 1024 * 1024) opt := transfer.UploadOption{ ExpectedReplica: 1, TaskSize: 10, SkipTx: true, FinalityRequired: transfer.TransactionPacked, FastMode: true, Method: "min", FullTrusted: true, } txHashes, roots, err := indexerClient.SplitableUpload(ctx, w3client, file, fragmentSize, opt) if err != nil { // Handle error } ``` `fragmentSize` controls the split size for large files. The returned `roots` contain the merkle root(s) to download later. ### File Hash Calculation Calculate a file's Merkle root hash for identification: ```go rootHash, err := core.MerkleRoot(filePath) if err != nil { // Handle error } fmt.Printf("File hash: %s\n", rootHash.String()) ``` :::info Important Save the root hash - you'll need it to download the file later! ::: ### File Download Download files from the network: ```go rootHex := rootHash.String() err = indexerClient.Download(ctx, rootHex, outputPath, withProof) if err != nil { // Handle error } ``` `withProof` enables merkle proof verification during download. ## Best Practices 1. **Error Handling**: Implement proper error handling and cleanup 2. **Context Management**: Use contexts for operation timeouts and cancellation 3. **Resource Cleanup**: Always close clients when done using `defer client.Close()` 4. **Verification**: Enable proof verification for sensitive files 5. **Monitoring**: Track transaction status for important uploads ## Additional Resources - [Go SDK Repository](https://github.com/0gfoundation/0g-storage-client) - [Go Starter Kit](https://github.com/0gfoundation/0g-storage-go-starter-kit) ## Installation Install the SDK and its peer dependency: ```bash npm install @0gfoundation/0g-storage-ts-sdk ethers ``` :::note `ethers` is a required peer dependency for blockchain interactions ::: ## Setup ### Import Required Modules ```javascript import { ZgFile, Indexer, MemData } from '@0gfoundation/0g-storage-ts-sdk'; import { ethers } from 'ethers'; ``` ### Initialize Configuration ```javascript // Network endpoints — see network overview docs for current values // Turbo indexer (recommended): const RPC_URL = 'https://evmrpc-testnet.0g.ai'; const INDEXER_RPC = 'https://indexer-storage-testnet-turbo.0g.ai'; // Initialize provider and signer const provider = new ethers.JsonRpcProvider(RPC_URL); const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider); // Initialize indexer — flow contract is auto-discovered const indexer = new Indexer(INDEXER_RPC); ``` :::info Turbo vs Standard 0G Storage has two independent networks: **Turbo** (faster, higher fees) and **Standard** (slower, lower fees). Each uses a different indexer URL. The SDK auto-discovers the correct flow contract from the indexer. See [Testnet](/developer-hub/testnet/testnet-overview) or [Mainnet](/developer-hub/mainnet/mainnet-overview) for current endpoints. ::: ## Core Operations ### File Upload Upload a file from the filesystem: ```javascript async function uploadFile(filePath) { const file = await ZgFile.fromFilePath(filePath); // Must call merkleTree() before upload — populates internal state const [tree, treeErr] = await file.merkleTree(); if (treeErr !== null) throw new Error(`Merkle tree error: ${treeErr}`); console.log("Root Hash:", tree?.rootHash()); const [tx, uploadErr] = await indexer.upload(file, RPC_URL, signer); if (uploadErr !== null) throw new Error(`Upload error: ${uploadErr}`); await file.close(); // Always close when done // Handle both single and fragmented (>4GB) responses if ('rootHash' in tx) { return { rootHash: tx.rootHash, txHash: tx.txHash }; } else { return { rootHashes: tx.rootHashes, txHashes: tx.txHashes }; } } ``` ### Upload In-Memory Data Upload strings or buffers without writing to disk using `MemData`: ```javascript const data = new TextEncoder().encode('Hello, 0G Storage!'); const memData = new MemData(data); const [tree, treeErr] = await memData.merkleTree(); const [tx, err] = await indexer.upload(memData, RPC_URL, signer); ``` ### File Download Download with optional verification: ```javascript async function downloadFromIndexer(rootHash, outputPath) { // withProof = true enables Merkle proof verification const err = await indexer.download(rootHash, outputPath, true); if (err !== null) { throw new Error(`Download error: ${err}`); } console.log("Download successful!"); } ``` ### Key-Value Storage Store and retrieve key-value data: ```javascript // Upload data to 0G-KV async function uploadToKV(streamId, key, value) { const [nodes, err] = await indexer.selectNodes(1); if (err !== null) { throw new Error(`Error selecting nodes: ${err}`); } const batcher = new Batcher(1, nodes, flowContract, RPC_URL); const keyBytes = Uint8Array.from(Buffer.from(key, 'utf-8')); const valueBytes = Uint8Array.from(Buffer.from(value, 'utf-8')); batcher.streamDataBuilder.set(streamId, keyBytes, valueBytes); const [tx, batchErr] = await batcher.exec(); if (batchErr !== null) { throw new Error(`Batch execution error: ${batchErr}`); } console.log("KV upload successful! TX:", tx); } // Download data from 0G-KV async function downloadFromKV(streamId, key) { const kvClient = new KvClient("http://3.101.147.150:6789"); const keyBytes = Uint8Array.from(Buffer.from(key, 'utf-8')); const value = await kvClient.getValue(streamId, ethers.encodeBase64(keyBytes)); return value; } ``` ### Browser Support For browser environments, use the SDK's `Blob` class (alias it to avoid collision with native `Blob`): ```javascript import { Blob as ZgBlob, Indexer } from '@0gfoundation/0g-storage-ts-sdk'; import { BrowserProvider } from 'ethers'; // Connect wallet via MetaMask const provider = new BrowserProvider(window.ethereum); await provider.send('eth_requestAccounts', []); const signer = await provider.getSigner(); // Upload a browser File object const zgBlob = new ZgBlob(fileInput.files[0]); const [tree, treeErr] = await zgBlob.merkleTree(); const indexer = new Indexer(INDEXER_RPC); const [tx, err] = await indexer.upload(zgBlob, RPC_URL, signer); ``` :::note Browser Downloads `indexer.download()` uses `fs.appendFileSync` internally and does not work in browsers. For browser downloads, use `StorageNode.downloadSegmentByTxSeq()` to fetch segments manually and reassemble in memory. See the [TypeScript Starter Kit](https://github.com/0gfoundation/0g-storage-ts-starter-kit) `web/src/storage.ts` for a complete working implementation. ::: :::caution Vite/Webpack Setup The SDK imports Node.js modules (`fs`, `crypto`) at load time. You need polyfills and stub aliases for browser bundlers. See the starter kit's `web/vite.config.ts` for a working Vite configuration with `vite-plugin-node-polyfills`. ::: ### Encryption & Decryption :::note Requires `@0gfoundation/0g-storage-ts-sdk` v1.2.6 or later. ::: Files are encrypted client-side before upload — the 0G network never sees plaintext. A compact header (17–50 bytes) is prepended so the SDK can auto-detect encryption mode on download. | Mode | Key material | Header size | |------|-------------|-------------| | `aes256` | 32-byte symmetric key | 17 bytes | | `ecies` | secp256k1 keypair | 50 bytes | #### AES-256 ```javascript import { ZgFile, Indexer } from '@0gfoundation/0g-storage-ts-sdk'; import { ethers } from 'ethers'; const indexer = new Indexer(indexerRpc); const signer = new ethers.Wallet(privateKey, provider); // save this: there is no server-side recovery const key = crypto.randomBytes(32); // Node.js — or crypto.getRandomValues in browser const file = await ZgFile.fromFilePath('./secret.txt'); const [tx, err] = await indexer.upload(file, rpcUrl, signer, { encryption: { type: 'aes256', key }, }); // Download + decrypt const [blob, dlErr] = await indexer.downloadToBlob(rootHash, { proof: true, decryption: { symmetricKey: key }, }); ``` #### ECIES For encrypt-to-self, your wallet's existing secp256k1 key works for both storage signing and decryption. Pass any recipient's compressed public key to encrypt for someone else. ```javascript import { ZgFile, Indexer } from '@0gfoundation/0g-storage-ts-sdk'; import { ethers } from 'ethers'; const wallet = new ethers.Wallet(privateKey, provider); const recipientPubKey = ethers.SigningKey.computePublicKey( wallet.signingKey.publicKey, true // true = compressed 33-byte key ); const file = await ZgFile.fromFilePath('./secret.txt'); const [tx, err] = await indexer.upload(file, rpcUrl, signer, { encryption: { type: 'ecies', recipientPubKey }, }); // Download + decrypt const [blob, dlErr] = await indexer.downloadToBlob(rootHash, { proof: true, decryption: { privateKey }, }); ``` #### Detecting encryption mode ```javascript import { Indexer } from '@0gfoundation/0g-storage-ts-sdk'; const [header, err] = await indexer.peekHeader(rootHash); // returns null for plaintext files // header.version === 1 → aes256 // header.version === 2 → ecies ``` :::note Wrong key does not throw — `downloadToBlob` silently returns raw ciphertext if the key doesn't match. Call `peekHeader` first if you are unsure whether a file is encrypted. `indexer.download()` does not support decryption. For encrypted files, always use `indexer.downloadToBlob()`. Large files will be fully buffered in memory. ::: ## Best Practices 1. **Initialize Once**: Create the indexer once and reuse it for multiple operations 2. **Handle Errors**: Always implement proper error handling for network issues 3. **Use Appropriate Methods**: Use `ZgFile.fromFilePath` for Node.js and `Blob` for browsers 4. **Secure Keys**: Never expose private keys in client-side code 5. **Close Resources**: Remember to call `file.close()` after operations ## Additional Resources - [TypeScript SDK Repository](https://github.com/0gfoundation/0g-storage-ts-sdk) - [TypeScript Starter Kit](https://github.com/0gfoundation/0g-storage-ts-starter-kit) — Scripts, library, and browser UI with MetaMask --- *Need more control? Consider running your own [storage node](/run-a-node/storage-node) to participate in the network and earn rewards.* --- ## Storage CLI Source: https://docs.0g.ai/developer-hub/building-on-0g/storage/storage-cli.md The 0G Storage CLI is your command-line gateway to interact directly with the 0G Storage network. It simplifies the process of uploading and downloading files while providing full control over your decentralized storage operations. ## Why Use the CLI? - **Direct Control**: Manage data location and versioning with precision - **Automation Ready**: Build scripts and cron jobs for regular operations - **Full Feature Access**: Access all storage and KV operations from the terminal - **Developer Friendly**: Perfect for integrating into your development workflow :::tip Web-Based Alternative For a quick and easy web interface, try the [0G Storage Web Tool](https://storagescan-galileo.0g.ai/tool) - perfect for one-off uploads and downloads. ::: ## Installation ### Prerequisites - Go 1.18 or higher installed on your system - Git for cloning the repository ### Setup Steps **1. Clone the Repository** ```bash git clone https://github.com/0gfoundation/0g-storage-client.git cd 0g-storage-client ``` **2. Build the Binary** ```bash go build ``` **3. Add to PATH** (Optional but recommended) ```bash # Move binary to Go bin directory mv 0g-storage-client ~/go/bin # Add to PATH if not already configured export PATH=~/go/bin:$PATH ``` ## Command Overview The CLI provides a comprehensive set of commands for storage operations: ```text 0g-storage-client [command] [flags] Available Commands: upload Upload file to 0G Storage network download Download file from 0G Storage network upload-dir Upload directory to 0G Storage network download-dir Download directory from 0G Storage network diff-dir Diff directory from 0G Storage network gen Generate test files kv-write Write to KV streams kv-read Read KV streams gateway Start gateway service indexer Start indexer service deploy Deploy storage contracts completion Generate shell completion scripts help Get help for any command Global Flags: --gas-limit uint Custom gas limit to send transaction --gas-price uint Custom gas price to send transaction --log-level string Log level (default "info") --log-color-disabled Force to disable colorful logs --rpc-retry-count int Retry count for rpc request (default 5) --rpc-retry-interval duration Retry interval for rpc request (default 5s) --rpc-timeout duration Timeout for single rpc request (default 30s) --web3-log-enabled Enable Web3 RPC logging ``` ## Core Operations ### File Upload Upload files to the 0G Storage network using the indexer service or explicit nodes: ```bash 0g-storage-client upload \ --url \ --key \ --indexer \ --file ``` **Parameters:** `--url` is the chain RPC endpoint, `--key` is your private key, and `--file` is the path to the file you want to upload. Use exactly one of `--indexer` or `--node`. Common flags include `--tags`, `--submitter`, `--expected-replica`, `--skip-tx`, `--finality-required`, `--task-size`, `--fast-mode`, `--fragment-size`, `--routines`, `--fee`, `--nonce`, `--max-gas-price`, `--n-retries`, `--step`, `--method`, `--full-trusted`, `--timeout`, `--flow-address`, and `--market-address`. Fee notes (turbo): - `unitPrice = 11 / pricePerToken / 1024 * 256`. If `pricePerToken = 1`, then `unitPrice = 2.75` (tokens), or `2.75e18` 0G. - `pricePerSector(256B)/month = lifetimeMonth * unitPrice * 1e18 / 1024 / 1024 / 1024` (no `/12` since $11 is per TB per month). ### File Download Download files from the network using the indexer or explicit nodes: ```bash 0g-storage-client download \ --indexer \ --root \ --file ``` **Parameters:** `--file` is the output path. Use exactly one of `--indexer` or `--node`. Use exactly one of `--root` or `--roots`. ### Download with Verification Enable proof verification for enhanced security: ```bash 0g-storage-client download \ --indexer \ --root \ --file \ --proof ``` The `--proof` flag requests cryptographic proof of data integrity from the storage node. ### Directory Upload Upload an entire directory using explicit storage nodes: ```bash 0g-storage-client upload-dir \ --url \ --key \ --node \ --file ``` ### Directory Download Download a directory by root: ```bash 0g-storage-client download-dir \ --indexer \ --root \ --file ``` ### Directory Diff Compare a local directory with the on-chain version: ```bash 0g-storage-client diff-dir \ --indexer \ --root \ --file ``` ## Practical Examples ### Upload Example ```bash # Upload a document to 0G Storage 0g-storage-client upload \ --url \ --key YOUR_PRIVATE_KEY \ --indexer \ --file ./documents/report.pdf # Output: # ✓ File uploaded successfully # Root hash: 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 # Transaction: 0x742d35cc6634c0532925a3b844bc454e8e4a0e3f... ``` ### Download Example ```bash # Download file using root hash 0g-storage-client download \ --indexer \ --root 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 \ --file ./downloads/report.pdf # With verification 0g-storage-client download \ --indexer \ --root 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 \ --file ./downloads/report.pdf \ --proof ``` ## Key-Value Operations ### Write to KV Store (Batch Operations) Write multiple key-value pairs in a single operation: ```bash 0g-storage-client kv-write \ --url \ --key \ --indexer \ --stream-id \ --stream-keys \ --stream-values ``` **Important:** `--stream-keys` and `--stream-values` are comma-separated string lists and their length must be equal. You can use `--indexer` for node selection or pass storage nodes directly with `--node`. If `--indexer` is omitted, `--node` is required. **Example:** ```bash 0g-storage-client kv-write \ --url \ --key YOUR_PRIVATE_KEY \ --indexer \ --stream-id 1 \ --stream-keys "key1,key2,key3" \ --stream-values "value1,value2,value3" ``` ### Read from KV Store ```bash 0g-storage-client kv-read \ --node \ --stream-id \ --stream-keys ``` :::info KV Read Endpoint Note that for KV read operations, you need to specify `--node` as the URL of a KV node, not the indexer endpoint. ::: ## RESTful API Gateway The indexer service provides a RESTful API gateway for easy HTTP-based file access: ### File Downloads via HTTP **By Transaction Sequence Number:** ```text GET /file?txSeq=7 ``` **By File Merkle Root:** ```text GET /file?root=0x0376e0d95e483b62d5100968ed17fe1b1d84f0bc5d9bda8000cdfd3f39a59927 ``` **With Custom Filename:** ```text GET /file?txSeq=7&name=foo.log ``` ### Folder Support Download specific files from within structured folders: **By Transaction Sequence:** ```text GET /file/{txSeq}/path/to/file ``` **By Merkle Root:** ```text GET /file/{merkleRoot}/path/to/file ``` ## Advanced Features ### Custom Gas Settings Control transaction costs with custom gas parameters: ```bash 0g-storage-client upload \ --gas-limit 3000000 \ --gas-price 10000000000 \ # ... other parameters ``` ### RPC Configuration Configure RPC retry behavior and timeouts: ```bash 0g-storage-client upload \ --rpc-retry-count 10 \ --rpc-retry-interval 3s \ --rpc-timeout 60s \ # ... other parameters ``` ### Logging Configuration Adjust logging for debugging: ```bash # Verbose logging with Web3 details 0g-storage-client upload \ --log-level debug \ --web3-log-enabled \ # ... other parameters # Minimal logging 0g-storage-client download \ --log-level error \ --log-color-disabled \ # ... other parameters ``` ### Shell Completion Enable tab completion for easier command entry: ```bash # Bash 0g-storage-client completion bash > /etc/bash_completion.d/0g-storage-client # Zsh 0g-storage-client completion zsh > "${fpath[1]}/_0g-storage-client" # Fish 0g-storage-client completion fish > ~/.config/fish/completions/0g-storage-client.fish ``` ## Indexer Service The indexer service provides two types of storage node discovery: ### Trusted Nodes Well-maintained nodes that provide stable and reliable service. ### Discovered Nodes Nodes discovered automatically through the P2P network. The indexer intelligently routes data to appropriate storage nodes based on their shard configurations, eliminating the need to manually specify storage nodes or contract addresses. ## Important Considerations ### Network Configuration :::info Required Information **RPC endpoints** and **indexer endpoints** are published in the network overview docs. Use the current values for your network. Keep private keys secure and never share them. ::: ### File Management - **Root Hash Storage**: Save file root hashes after upload - they're required for downloads - **Transaction Monitoring**: Track upload transactions on the blockchain explorer - **Indexer Benefits**: The indexer automatically selects optimal storage nodes for better reliability ## Running Services ### Indexer Service The indexer helps users find suitable storage nodes: ```bash 0g-storage-client indexer \ --endpoint :12345 \ --node ``` Or start with a trusted node list: ```bash 0g-storage-client indexer \ --endpoint :12345 \ --trusted ``` ### Gateway Service Run a gateway to provide HTTP access to storage: ```bash 0g-storage-client gateway \ --nodes ``` Optionally specify a local file repo: ```bash 0g-storage-client gateway \ --nodes \ --repo ``` ## Automation Examples ### Backup Script Create automated backup scripts: ```bash #!/bin/bash # backup.sh - Daily backup to 0G Storage DATE=$(date +%Y%m%d) BACKUP_FILE="/backups/daily-${DATE}.tar.gz" # Create backup tar -czf $BACKUP_FILE /important/data # Upload to 0G ROOT_HASH=$(0g-storage-client upload \ --url $RPC_URL \ --key $PRIVATE_KEY \ --indexer $INDEXER_URL \ --file $BACKUP_FILE | grep "root =" | awk '{print $NF}') # Save root hash echo "${DATE}: ${ROOT_HASH}" >> /backups/manifest.txt ``` ### Monitoring Integration Monitor uploads with logging: ```bash # upload-with-monitoring.sh 0g-storage-client upload \ --file $1 \ --log-level info \ # ... other parameters \ 2>&1 | tee -a /var/log/0g-uploads.log ``` ## Troubleshooting
**Upload fails with "insufficient funds" error** Ensure your wallet has enough tokens for: - Gas fees on 0G Chain - Storage fees for the file size Check balance: Use a blockchain explorer or wallet to verify funds.
**"Indexer not found" error during upload/download** This can happen if: - The indexer service is offline - The indexer endpoint URL is incorrect - Network connectivity issues Verify the indexer endpoint and try again.
**RPC timeout errors** If you experience RPC timeouts, try adjusting the timeout settings: ```bash --rpc-timeout 60s --rpc-retry-count 10 --rpc-retry-interval 3s ```
## Best Practices 1. **Security First**: Store private keys in environment variables, not command line 2. **Backup Root Hashes**: Always save file root hashes after uploads 3. **Use Verification**: Enable `--proof` for important downloads 4. **Monitor Transactions**: Track uploads on the blockchain explorer 5. **Test with Gen**: Use the `gen` command to create test files for development 6. **HTTP Access**: Leverage the RESTful API for web applications and integrations 7. **Batch KV Operations**: Use comma-separated lists for efficient key-value operations --- *Need more control? Consider running your own [storage node](/run-a-node/storage-node) to participate in the network and earn rewards.* --- ## Getting Started Source: https://docs.0g.ai/developer-hub/getting-started.md ## The Problem We Solve Your AI application needs: - **Massive storage** for training data (TBs of datasets) - **GPU compute** for model inference ($10K+/month on centralized providers) - **Fast data availability** for real-time responses - **Decentralization** without sacrificing performance :::success Modular Infrastructure 0G provides all of this in one integrated ecosystem - or use just the parts you need. ::: ## 0G Services ### 0G Chain EVM-compatible blockchain optimized for AI - [Deploy Contracts](/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) - [Precompiles Reference](/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-overview) - [Chain Architecture](/concepts/chain) ### 0G Compute Decentralized GPU marketplace for AI workloads - [Overview & Architecture](/developer-hub/building-on-0g/compute-network/overview) - [Router API (recommended)](/developer-hub/building-on-0g/compute-network/router/overview) - [Direct (SDK + per-provider accounts)](/developer-hub/building-on-0g/compute-network/direct) - [Become a Provider](/developer-hub/building-on-0g/compute-network/inference-provider) ### 0G Storage High-performance storage for massive datasets - [SDK Integration](/developer-hub/building-on-0g/storage/sdk) - [CLI Commands](/developer-hub/building-on-0g/storage/storage-cli) - [Architecture Details](/concepts/storage) ### 0G DA Scalable data availability for any chain - [Technical Deep Dive](/developer-hub/building-on-0g/da-deep-dive) - [Integration Guide](/developer-hub/building-on-0g/da-integration) - [Rollup Integrations](/developer-hub/building-on-0g/rollups-and-appchains/op-stack-on-0g-da) ## Community Projects Explore our growing ecosystem of DeAI applications in the [awesome-0g](https://github.com/0gfoundation/awesome-0g) repository, which showcases community projects, tools, and resources built on 0G. --- Ready to build? Pick a service above and start in minutes, or [join our Discord](https://discord.gg/0gLabs) for help. --- ## Mainnet Overview Source: https://docs.0g.ai/developer-hub/mainnet/mainnet-overview.md Build and run production workloads on the 0G Mainnet. :::tip Mainnet Explorer 🔍 **[Explore Mainnet Activity](https://explorer.0g.ai/mainnet/home)** ::: ## Network Details | Parameters | Network Details | |----------------|---| | **Network Name** | 0G Mainnet | | **Chain ID** | 16661 | | **Token Symbol** | 0G | | **RPC URL** | `https://evmrpc.0g.ai` | | **Storage Indexer** | `https://indexer-storage-turbo.0g.ai` | | **Block Explorer** | `https://chainscan.0g.ai` | #### ✅ 3rd Party RPCs (Recommended for production) - [QuickNode](https://www.quicknode.com/chains/0g) - [ThirdWeb](https://thirdweb.com/0g-aristotle) - [Ankr](https://www.ankr.com/rpc/0g/) - [dRPC](https://drpc.org/chainlist/0g-mainnet-rpc) ### Add Network to Wallet :::info Alternative RPC Providers For redundancy in production apps, consider adding multiple RPC providers where available. ::: ## Contract Addresses **0G Storage** - Flow: `0x62D4144dB0F0a6fBBaeb6296c785C71B3D57C526` - Mine: `0xCd01c5Cd953971CE4C2c9bFb95610236a7F414fe` - Reward: `0x457aC76B58ffcDc118AABD6DbC63ff9072880870` ## Developer Tools - **Chain Explorer**: `https://chainscan.0g.ai (https://chainscan.0g.ai)` --- ## 0G Galileo Testnet Source: https://docs.0g.ai/developer-hub/testnet/testnet-overview.md Test your applications on 0G's infrastructure without real costs or risks. :::tip Testnet Explorer 🔍 **[Explore Testnet Activity](https://explorer.0g.ai/testnet/home)** ::: ## Network Details | Parameters | Network Details | |----------------|---| | **Network Name** | 0G Galileo Testnet | | **Chain ID** | 16602 | | **Token Symbol** | 0G | | **RPC URL** | `https://evmrpc-testnet.0g.ai` (development only, use a 3rd party RPC for production) | | **Block Explorer** | `https://chainscan-galileo.0g.ai` | | **Faucet** | https://faucet.0g.ai | | **Faucet (Google Cloud)** | https://cloud.google.com/application/web3/faucet/0g/galileo | #### ✅ 3rd Party RPCs (Recommended for production) - [QuickNode](https://www.quicknode.com/chains/0g) - [ThirdWeb](https://thirdweb.com/16602) - [Ankr](https://www.ankr.com/rpc/0g/) - [dRPC NodeCloud](https://drpc.org/chainlist/0g-galileo-testnet-rpc) ## Getting Started ### Step 1: Add Network to Wallet export const AddNetworkSection = () => ( <> Remove any old 0G testnet configurations before adding Galileo (steps below). );
Removing an old 0G testnet from MetaMask The old testnet versions are no longer active. Remove them from your MetaMask network list before adding the current **0G Galileo Testnet**, to avoid conflicts. 1. Open MetaMask and click the network dropdown menu at the top. ![MetaMask network dropdown](/img/step%201.png) 2. Select any network *other* than **0G-Testnet**. ![Switching network](/img/step%202.png) 3. Open the network dropdown menu again. 4. Find **0G-Testnet** in the list and click the three vertical dots icon next to it. ![Three dots menu for network](/img/step%203.png) 5. Select the **Delete** option from the menu. 6. Confirm the deletion when prompted by MetaMask. 7. Once removed, click the "Add to MetaMask" button above again.
### Step 2: Get Test Tokens Visit the [0G Faucet](https://faucet.0g.ai) or the [Google Cloud Faucet](https://cloud.google.com/application/web3/faucet/0g/galileo) to receive free testnet tokens. **Daily Limit**: 0.1 0G per wallet. ### Step 3: Start Building Choose your integration: - [Deploy Smart Contracts](/developer-hub/building-on-0g/contracts-on-0g/deploy-contracts) - [Use Storage SDK](/developer-hub/building-on-0g/storage/sdk) - [Access Compute Network](/developer-hub/building-on-0g/compute-network/router/overview) - [Integrate DA Layer](/developer-hub/building-on-0g/da-integration) ### Contract Addresses :::caution Addresses may change during testnet. ::: **0G Storage** - Flow: `0x22E03a6A89B950F1c82ec5e74F8eCa321a105296` - Mine: `0x00A9E9604b0538e06b268Fb297Df333337f9593b` - Reward: `0xA97B57b4BdFEA2D0a25e535bd849ad4e6C440A69` **0G DA** - DAEntrance: `0xE75A073dA5bb7b0eC622170Fd268f35E675a957B` ## Developer Tools ### Block Explorers - **[Chain Explorer](https://chainscan-galileo.0g.ai)**: View transactions, blocks, and smart contracts - **[Storage Explorer](https://storagescan-galileo.0g.ai)**: Track storage operations and metrics
Development RPC :::warning Development Only This endpoint is for development purposes and should not be used in production applications. ::: `https://evmrpc-testnet.0g.ai`
## Faucet - Use the [official Faucet](https://faucet.0g.ai) or the [Google Cloud Faucet](https://cloud.google.com/application/web3/faucet/0g/galileo) to request tokens. Each user can receive up to 0.1 0G token per day, which is sufficient for most testing needs. - If you require more than 0.1 0G token per day, please reach out in our vibrant [discord](https://discord.com/invite/0glabs) community to request additional tokens. --- ## 0G Documentation Source: https://docs.0g.ai/index.md Build the Future of Decentralized AI Quick Start Learn Concepts Join Testnet Connect to Galileo testnet and start building your first dApp on 0G Connect to Testnet → AI Alignment Node Learn more about the AI Alignment Node operation Learn More → Inference Integrate AI inference into your applications with SDKs View Docs → Storage SDK Store and retrieve massive datasets with Go and TypeScript client libraries View Docs → Fine-tuning Customize AI models for your specific use case with our command-line tools View Docs → Run a Validator Secure the network and earn rewards by running a validator node Setup Guide → Ready to Build? Join thousands of developers building the future of decentralized AI View Full Documentation --- ## How to Get 0G Token Source: https://docs.0g.ai/introduction/how-to-get-0g.md :::tip Interactive Guide Prefer a guided path? **[get.0g.ai](https://get.0g.ai)** is the official interactive guide to acquiring $0G. Pick your starting point (fiat, another chain, an exchange, DeFi, or a wallet) and it walks you through step by step. ::: :::info Network Details - **Token**: Native gas token (EVM-compatible) - **Chain ID**: 16661 - **Explorer**: [https://chainscan.0g.ai](https://chainscan.0g.ai) - **Mainnet Launch**: September 2025 ::: ## Official Token Contracts On the 0G Mainnet, the 0G token is the **native gas token**. Like ETH on Ethereum, it has no contract address (some interfaces display it as `0x0000…0000`). Every official contract representation is listed below. **Any other contract claiming to be $0G, on any network, is not official.** | Network | Token | Contract Address | |---------|-------|------------------| | 0G Mainnet (chain ID 16661) | W0G (Wrapped 0G) | [`0x1Cd0690fF9a693f5EF2dD976660a8dAFc81A109c`](https://chainscan.0g.ai/address/0x1Cd0690fF9a693f5EF2dD976660a8dAFc81A109c) | | Ethereum (chain ID 1) | 0G (official bridged token) | [`0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE`](https://etherscan.io/token/0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE) | | BNB Chain (chain ID 56) | 0G (official bridged token) | [`0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE`](https://bscscan.com/token/0x4B948d64dE1F71fCd12fB586f4c776421a35b3eE) | All three tokens use 18 decimals. The official bridged token deliberately shares the **same address on Ethereum and BNB Chain**, and moves to and from the 0G network via [Stargate](https://stargate.finance). W0G is the canonical wrapped form of the native token on the 0G chain; see [Wrapped 0G Base](/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-wrappedogbase) for details. ## Centralized Exchanges The most straightforward way to acquire $0G is through centralized exchanges. After purchasing, withdraw directly to the **0G Mainnet** (select "0G Chain" or "0G Mainnet" as the withdrawal network). All exchanges below support withdrawals to the native 0G network. Always confirm the withdrawal network in-app before transferring, as availability can be paused during network upgrades. ### Spot Trading | Exchange | Trading Pairs | |----------|---------------| | **[Binance](https://www.binance.com/en/trade/0G_USDT)** | 0G/USDT, 0G/USDC, 0G/TRY | | **[HTX](https://www.htx.com/trade/0g_usdt)** | 0G/USDT | | **[Bybit](https://www.bybit.com/en/trade/spot/0G/USDT)** | 0G/USDT | | **[MEXC](https://www.mexc.com/exchange/0G_USDT)** | 0G/USDT, 0G/USDC | | **[KuCoin](https://www.kucoin.com/trade/0G-USDT)** | 0G/USDT | | **[Gate.io](https://www.gate.io/trade/0G_USDT)** | 0G/USDT | | **[Bitget](https://www.bitget.com/spot/0GUSDT)** | 0G/USDT | | **[HashKey Exchange](https://global.hashkey.com/en-US/spot/0G_USDT)** | 0G/USDT | | **[LBank](https://www.lbank.com/trade/0g_usdt)** | 0G/USDT, 0G/USDC | | **[Upbit](https://upbit.com/exchange?code=CRIX.UPBIT.KRW-0G)** | 0G/KRW, 0G/BTC, 0G/USDT | | **[Kraken](https://www.kraken.com/prices/0g)** | 0G/USD, 0G/EUR | | **[Bithumb](https://www.bithumb.com/react/trade/order/0G-KRW)** | 0G/KRW | ## Buy on Fomo Buy the [official bridged $0G](#official-token-contracts) directly on [Fomo](https://fomo.family/coin?address=0x4b948d64de1f71fcd12fb586f4c776421a35b3ee&chainId=56&r=vargs_g&source=share_link). ## Bridge to 0G Chain **[XSwap](https://xswap.link/)** is the official bridge for the 0G network, powered by [Chainlink CCIP](https://docs.chain.link/ccip/directory/mainnet/chain/0g-mainnet). ### XSwap Bridge - **URL**: [https://xswap.link/bridge?toChain=16661](https://xswap.link/bridge?toChain=16661) - **Supported Assets**: USDC and other tokens - **Networks**: Ethereum ↔ 0G (with more chains coming) - **Security**: Powered by [Chainlink CCIP](https://docs.chain.link/ccip/directory/mainnet/chain/0g-mainnet) with enterprise-grade security **How to Bridge:** 1. Visit [xswap.link/bridge?toChain=16661](https://xswap.link/bridge?toChain=16661) 2. Connect your wallet (MetaMask, SafePal, etc.) 3. Select source chain (e.g., Ethereum) and 0G as destination 4. Choose asset to bridge (e.g., USDC) 5. Confirm transaction and wait for bridging to complete 6. Once bridged, swap your assets to $0G on the 0G Hub ### Khalani TokenFlight (Cross-Chain Swap on 0G Hub) - **URL**: [https://hub.0g.ai/khalani/transfer](https://hub.0g.ai/khalani/transfer) - **Networks**: 20 chains, including Ethereum, BNB Chain, Arbitrum, Base, Solana, Monad, Bitcoin and Tron - **How it works**: Intent-based routing with atomic settlement. Select a source chain and token; TokenFlight finds the best route and delivers on 0G. ### More Bridges & Aggregators | Bridge | Route to 0G | Notes | |--------|-------------|-------| | **[Jumper](https://jumper.exchange)** | 60+ chains | LI.FI aggregator; includes a gas-refuel option | | **[Interport](https://interport.fi)** | 10+ chains incl. Solana & Monad | Gas Transfer feature delivers native 0G for fees | | **[Stargate](https://stargate.finance)** | Ethereum & BNB Chain | Bridges $0G, plus WBTC / WETH / cbBTC to 0G | | **[Wormhole Portal](https://portalbridge.com)** | Solana and 15+ chains | Wrapped-asset token bridge | | **[0G Hub Bridge](https://hub.0g.ai/bridge)** | Ethereum ↔ 0G | Moves W0G (wrapped 0G) | | **[Gas.zip](https://www.gas.zip)** | Gas refuel only | Tops up a small amount of native 0G for transaction fees | :::note For developers [LI.FI](https://li.fi/), the bridge & swap aggregation engine behind Jumper, supports 0G Mainnet directly (chain key `zerog`, chain ID `16661`). Use the [LI.FI API](https://docs.li.fi/) or [SDK](https://docs.li.fi/sdk/overview) to quote and execute cross-chain swaps into 0G programmatically, e.g. `GET https://li.quest/v1/quote?toChain=16661&...`. ::: ## Swap on 0G Chain Once you have assets on the 0G network, swap them for native $0G tokens. ### 0G Hub (Recommended) - **URL**: [https://hub.0g.ai/swap](https://hub.0g.ai/swap) - **Features**: Official swap interface for the 0G ecosystem - **Powered by**: [Jaine](https://jaine.app/) - **Available Pairs**: Multiple trading pairs including ETH, USDT, USDC The 0G Hub provides seamless token swapping, portfolio tracking, and access to the entire 0G ecosystem. ## Wallet Setup To receive and hold $0G, you need a wallet that supports the 0G network. ### Supported Wallets Every wallet below detects the native $0G token automatically once the 0G network is added. | Wallet | Add 0G Network | |--------|----------------| | **[MetaMask](https://metamask.io/)** | Add manually (see [Mainnet Overview](/developer-hub/mainnet/mainnet-overview)) | | **[Rabby](https://rabby.io/)** | Built-in | | **[OKX Wallet](https://www.okx.com/web3)** | Built-in | | **[Bitget Wallet](https://web3.bitget.com/)** | Built-in | | **[Zerion](https://zerion.io/)** | Built-in | | **[Coinbase Wallet](https://www.coinbase.com/wallet)** | Add manually | | **[SafePal](https://www.safepal.com/)** | In-app network directory (App v3.9.0+) | | **[Trust Wallet](https://trustwallet.com/)** | Add manually | | **[TokenPocket](https://www.tokenpocket.pro/)** | In-app network directory | | **[Rainbow](https://rainbow.me/)** | Add manually | | **[Safe](https://safe.global/)** (multisig for teams & treasuries) | Built-in | | **[Fordefi](https://fordefi.com/)** (institutional MPC) | Built-in | | **[Ledger](https://www.ledger.com/)** (hardware wallet) | Built-in | ### Adding 0G Network For detailed instructions on adding the 0G network to your wallet, including RPC endpoints and network configuration, visit the [Mainnet Overview](/developer-hub/mainnet/mainnet-overview) page. --- For more information about the 0G network and its features, see [Understanding 0G](/introduction/understanding-0g). For a step-by-step path tailored to where you're starting from, use the interactive guide at [get.0g.ai](https://get.0g.ai). --- ## Understanding 0G Source: https://docs.0g.ai/introduction/understanding-0g.md ## Why 0G Exists AI (Artificial Intelligence) is rapidly advancing, but its powerful capabilities are largely confined to centralized systems & limited to a few large companies. Bringing AI onto the blockchain unlocks transformative potential: truly verifiable AI, user-owned data powering AI applications, and open, censorship-resistant AI development. However, a fundamental challenge has held back this vision: - **AI's Data Hunger:** AI models and datasets are massive. Existing blockchains make storing and accessing this data impossibly expensive and slow. - **Intense Compute Demands:** AI requires significant processing power, far beyond what traditional blockchains can offer efficiently. - **Need for Speed:** Real-time AI applications demand high throughput and low latency Without overcoming these hurdles, the dream of decentralized AI remains out of reach. **0G is built to break these barriers.** We provide the foundational infrastructure like high-performance storage, scalable compute, and a fast, modular blockchain—designed from the ground up to power the future of on-chain AI. ## What is 0G? 0G (Zero Gravity) is the first decentralized AI L1 chain that orchestrates hardware resources (storage, compute) and software assets (data, models) to handle AI workloads at scale. It bridges the gap between Web2 AI capabilities and Web3 decentralization. :::info 0G is building the global foundation for a better, fairer, and more open AI ecosystem, where power is distributed and innovation thrives ::: **How it works**: 0G provides four independent services that solve different pieces of the AI + blockchain puzzle: - **Storage** → Where to keep massive AI datasets - **Compute** → How to run AI models economically - **Chain** → Where to execute AI transactions quickly - **Data Availability** → How to ensure data is always accessible ## Modular Architecture :::tip Key Benefit of Modular Architecture: You DON'T need to use all of 0G! **Pick only what you need:** - **Already on Ethereum, Polygon, or any EVM chain?** Use 0G Storage and Compute directly from your existing smart contracts, no need to migrate. - **Building on Solana or other non-EVM chains?** Our SDKs support cross-chain integration - **Just need one service?** Use only 0G Storage or only 0G Compute ::: ## The 4 Components of 0G | Component | Works Independently? | Key Features & Use Cases | Cost Highlight | |-----------------------|--------------------------------------------------------|-----------------------------------------------------------------------------------|---------------------------------------| | **0G Chain** | ✅ Yes (Optional for other services) | AI-native EVM L1 for AI agents, DeFi with AI logic | Low gas fees in 0G token | | **0G Storage** | ✅ Yes (Any app/chain can access) | Store AI models (GBs-TBs), training datasets, user files, game assets | 10-100x cheaper than alternatives | | **0G Compute** | ✅ Yes (Any app/chain can access) | Run AI inference, model training, verifiable compute, ML pipelines | Pay-only-for-what-you-use | | **0G DA** | ✅ Yes (Works with any rollup/L1/L2) | Power gaming chains, AI rollups, high-frequency trading chains | Economical for high-volume DA | *\*0G Storage can be used completely standalone without any blockchain integration - perfect for traditional apps needing decentralized storage.* ## Key Concepts Explained Simply
**What is decentralized storage?** Instead of storing your files on one company's computer (like Google Drive), they're split and stored across hundreds of computers worldwide. **Why it matters**: If Google's servers crash, you lose access. With decentralized storage, even if 50 computers fail, your data is still safe and accessible.
**What is data availability?** It's a guarantee that your data can always be accessed when needed, like having multiple backup generators for your house. **Why it matters**: In blockchain, if data isn't available, the whole system can freeze. 0G ensures this never happens.
**What is an AI compute network?** It's like Uber for computing power - connect to available GPUs when you need to run AI models, pay only for what you use. **Why it matters**: Instead of buying expensive GPUs or relying on big tech companies, access computing power on-demand from a global network.
**What is a modular blockchain?** Like LEGO blocks, each part of the blockchain (storing data, processing transactions, reaching agreement) is separate and can be upgraded independently. **Why it matters**: Traditional blockchains are like old phones where you can't upgrade just the camera. Modular blockchains let you improve each part without rebuilding everything.
## Why "Zero Gravity"? "0G" represents "Zero Gravity" - the state where everything flows effortlessly. Just as astronauts move freely in zero gravity, data and AI computations flow seamlessly through our network without the heavy "gravity" of: - High costs - Slow speeds - Technical barriers - Platform lock-in ## What Can You Build? With 0G's technology, previously impossible use cases are now within reach: - **On-chain AI agents** that learn and evolve - **Decentralized ChatGPT** alternatives - **AI-powered DeFi** trading systems - **Medical AI** with patient-owned data - **Large-scale ML training** without AWS bills And this is just the beginning. ## Where to Go Next Now that you understand what 0G is and why it exists, here's how to dive deeper: **For Learners** → Read more about [Concepts](/concepts/chain) to understand how each component works **For Builders** → Jump into the [Developer Hub](/developer-hub/getting-started) to start building **For Operators** → Learn how to [Run a Node](/run-a-node/overview) and earn rewards ## Join the 0G Community - [Discord](https://discord.gg/0gLabs) - Get help and chat with builders - [X(Twitter)](https://x.com/0g_Labs) - Latest updates and announcements - [GitHub](https://github.com/0gfoundation/0g-doc) - Contribute to the project We're excited to have you on board as we build the future of Web3 × AI together! --- ## Vision & Mission Source: https://docs.0g.ai/introduction/vision-mission.md ## Our Mission: Make AI a Public Good At 0G, our mission is clear: **To Make AI a Public Good**. We believe that AI technology should be accessible, transparent, and beneficial to everyone, not just a select few. By building the trust layer for AI, we're creating the infrastructure that will enable this vision. ## Our Vision We envision a world where: - **AI is democratized**: Anyone can access and contribute to AI development without gatekeepers - **AI is transparent**: The models, data, and processes are open and verifiable - **AI is fair**: Resources and benefits are distributed equitably across the network - **AI is secure**: Decentralization ensures no single point of failure or control ## How We Achieve This Every component of our ecosystem contributes toward this goal: 1. **Open Infrastructure**: By providing decentralized storage, compute, and data availability, we remove the barriers to AI development 2. **Community Ownership**: Through our node network and governance model, the community owns and operates the infrastructure 3. **Economic Alignment**: Our tokenomics ensure that contributors are fairly rewarded for their participation 4. **Technical Excellence**: We build the fastest, most efficient infrastructure to make decentralized AI competitive with centralized alternatives ## Join Our Mission We invite you to join us in building the foundation for a decentralized AI future. Whether you're a developer, node operator, or community member, there's a place for you in the 0G ecosystem. Together, we're not just building technology – we're shaping the future of AI for the benefit of all humanity. ## Join the 0G Community - [Discord](https://discord.gg/0gLabs) - [X(Twitter)](https://x.com/0g_Labs) - [GitHub](https://github.com/0gfoundation/0g-doc) --- ## 0G AI Alignment Node - Guide Source: https://docs.0g.ai/node-sale/ai-alignment-node-user-guide.md --- ::::info **Who this is for & what you'll learn** - Run your own Alignment Node or delegate to a NAAS provider - Understand system requirements, setup steps, and monitoring - Learn NAAS models (commission vs prepaid) and how to delegate/undelegate :::: ## Overview The 0G AI Alignment Node system allows license holders to participate in the network either by running their own nodes or delegating to Node as a Service (NAAS) providers. This guide covers both options to help you choose the best approach for your needs. ## Choose Your Path ### Quick decision summary | Option | Best for | Setup time | Rewards | Maintenance | |-------|----------|-----------|---------|-------------| | **Option 1: [Delegate to NAAS](#option-1-delegating-to-naas-providers)** | Non-technical users | 2-3 Minutes | 100% (prepaid) or minus commission | Provider handles | | **Option 2: [Run your own](#option-2-running-your-own-node)** | Technical users | 1-2 Hours | 100% | You handle | --- ## Option 1: Delegating to NAAS Providers ### Understanding NAAS Models NAAS providers offer two delegation models: #### Commission-Based Model - **How it works:** NAAS provider takes a percentage of your rewards as commission - **Payment:** No upfront payment required - **Status:** Nodes start as "Active" immediately - **Best for:** Users who prefer sharing rewards over upfront payments #### Prepaid Model - **How it works:** Pay a fixed fee upfront for node operation - **Payment:** One-time or recurring prepaid fee - **Status:** Nodes start as "Expired" until payment is confirmed - **Best for:** Users who want predictable costs ### How to Delegate #### Step 1: Choose a NAAS Provider 1. Access the [0G Claim Portal](https://claim.0gfoundation.ai) 2. Navigate to the NAAS Providers section 3. Review available providers: - **Name & Description**: Provider details - **Commission Rate**: Percentage for commission-based model - **Prepaid Price**: Cost for prepaid nodes - **Reputation**: Community ratings and uptime statistics ![NAAS Providers](/img/naas.png) #### Step 2: Complete Provider Onboarding 1. Visit the selected NAAS provider's platform (URL provided in portal) 2. Complete their onboarding process: - Create an account - Choose delegation model (commission or prepaid) - If prepaid, complete payment 3. Receive your **Target NAAS Node Address** from the provider **Important:** Save this address - you'll need it for delegation. #### Step 3: Delegate Your Licenses 1. Return to the 0G Portal 2. Login with your wallet containing licenses 3. Navigate to "My Licenses" 4. Select license(s) to delegate 5. Choose "Delegate" action 6. Enter the **Target NAAS Node Address** provided by your NAAS provider 7. Confirm the transaction ![Delegate Licenses](/img/delegate.png) #### Step 4: Monitor Delegation Status Your delegation will show different statuses: | Status | Description | |--------|------------| | **Inactive** | License not delegated | | **Pending** | Delegation submitted, awaiting NAAS approval | | **Delegated** | Active and earning rewards | | **Expired** | Prepaid period ended or payment issue | ### Managing Your Delegation #### Checking Status 1. Access the 0G Portal 2. Navigate to "My Licenses" 3. View delegation status for each license #### Undelegating To reclaim your licenses: 1. Select delegated license(s) 2. Choose "Undelegate" 3. Confirm the transaction 4. Licenses immediately return to "Inactive" status **Note:** Undelegation is immediate and doesn't require NAAS approval. #### Switching Providers 1. First undelegate from current provider 2. Wait for transaction confirmation 3. Follow delegation steps with new provider ### NAAS Payment Management #### For Commission-Based: - Rewards automatically distributed after commission deduction - No action required from you - Monitor earnings in the portal #### For Prepaid: - Track expiration dates - Renew before expiration to avoid downtime - Provider will update status upon payment - Node shows "Expired" if payment lapses --- ## Option 2: Running Your Own Node ### System Requirements Before setting up your node, ensure your system meets these minimum specifications: | Component | Minimum Requirement | |-----------|-------------------| | **RAM** | 64 MB | | **CPU** | 1 x86 Core @ 2.1GHz | | **Disk Space** | 10 GB | | **Internet** | 10 Mbps connection | | **Network** | Port must be externally accessible (configure in firewall) | ### Installation & Setup #### Step 1: Download the Node Binary Download the latest 0G alignment node binary from the official repository: ```bash # Download the binary (replace with actual URL) wget https://github.com/0gfoundation/alignment-node-release/releases/download/v1.0.0/alignment-node.tar.gz tar -xzf alignment-node.tar.gz cd alignment-node chmod +x 0g-alignment-node ``` #### Step 2: Configure Environment 1. Copy the example environment file: ```bash cp .env.example .env ``` 2. Edit the `.env` file with your configuration: ```bash nano .env ``` 3. Configure the following parameters: ```bash export ZG_ALIGNMENT_NODE_LOG_LEVEL=debug export ZG_ALIGNMENT_NODE_SERVICE_IP="http://127.0.0.1:34567" # Full URL endpoint export ZG_ALIGNMENT_NODE_SERVICE_PRIVATEKEY=your_private_key_here ``` :::note The private key is the private key of the wallet you used to purchase the NFT. If the wallet doesn't have any NFTs, the wallet is not eligible to register as operator. ::: **Important Configuration Notes:** - **LOG_LEVEL**: Set to `debug` for troubleshooting, `info` for normal operation - **SERVICE_IP**: The ip of the service you are running. You need to add the external ip of the node to the `.env` file. The external ip is the ip of the node that is accessible from the internet. - **PRIVATEKEY**: Your wallet's private key that holds the alignment node license(s) #### Step 3: Network Configuration ::::warning **Open your service port** The port specified in your configuration must be accessible externally for consensus communication. Make sure this port is open in: - Cloud security groups/firewalls (AWS, Azure, GCP, etc.) - VPS provider firewalls - Local server firewall rules Steps vary by provider; consult your host's docs. :::: #### Step 4: Start Your Node 1. Load environment variables: ```bash source .env ``` 2. Register the operator: ```bash ./0g-alignment-node registerOperator --key --token-id --chain-id --rpc --contract ``` :::note The token id is the token id of the NFT you purchased. The private key is the private key of the wallet you used to purchase the NFT. If the wallet doesn't have any NFTs, the wallet is not eligible to register as operator. ::: **Configuration Details:** - **Chain ID**: `16661` (0G Mainnet) - **RPC URL**: `https://evmrpc.0g.ai` - **Alignment manager contract address**: `0x7BDc2aECC3CDaF0ce5a975adeA1C8d84Fd9Be3D9` (0G Mainnet) 3. Start the node: ```bash ./0g-alignment-node start --mainnet ``` 4. To run in background (recommended for production): ```bash nohup ./0g-alignment-node start --mainnet > node.log 2>&1 & ``` ### Monitoring Your Node View logs: ```bash tail -f node.log ``` ### Node command help ```bash ./0g-alignment-node --help ./0g-alignment-node --help ``` ::::tip **Healthy node checklist** - Status reports without errors - Logs show steady activity, no repeated crashes :::: ### Troubleshooting **Node not connecting:** - Verify port is open and accessible externally - Check your firewall/security group settings - Ensure private key has associated licenses **Node crashes:** - Check logs for errors - Verify system requirements are met - Ensure stable internet connection --- ## Best Practices ### For Self-Hosted Nodes 1. **Regular Updates**: Keep node binary updated 2. **Monitoring**: Set up alerts for downtime 3. **Backup**: Keep secure backup of private keys 4. **Security**: Use dedicated wallet for node operation 5. **Network**: Ensure stable internet connection ### For NAAS Delegation 1. **Research Providers**: Check reputation and uptime history 2. **Understand Terms**: Read commission rates and prepaid terms 3. **Monitor Status**: Regularly check delegation status 4. **Payment Tracking**: Set reminders for prepaid renewals 5. **Diversification**: Consider splitting licenses across providers --- --- ## Compliance and Regulatory Requirements Source: https://docs.0g.ai/node-sale/details/compliance-and-regulatory.md ## Regulation S Compliance The sale follows Regulation S guidelines, restricting U.S. persons from participating. The sale website, promotional content, and user interface clearly indicate these restrictions, and KYC verification is mandatory for claiming rewards to maintain regulatory adherence. Prospective participants are advised to review these conditions and understand that resale of node licenses is not permitted within the first 12 months. ## Information Disclosure All communications related to the sale are made with transparency but exclude any directed selling to U.S. persons. Information shared in marketing materials, promotional activities, and social media avoids U.S.-targeted content, aligning with compliance requirements to mitigate any regulatory risks. --- ## Incentives & Rewards Source: https://docs.0g.ai/node-sale/details/incentives-and-rewards.md ## Rebate/Commission Portal Tutorial ## How can node buyers create a referral code? Node buyers could share their wallet address as the referral code after they made a purchase, which gave a 10% rebate to their referrals. ## What rebate is available when using a referral code? Buyers who entered a referral code when purchasing a node received a 10% rebate on the total price. ## How will I receive my commission? (For Referrers)​ Commission for any successful node purchased through your referral can be claimed on the reward claim site, which opened after the public sale. Please refer to 0G X for access to the claim site. ## Vesting Terms Rewards from node operation vest over a three-year schedule, promoting consistent and long-term engagement. Vesting reduces the likelihood of short-term sales, fostering network stability and growth. ## Additional Community Incentives Partnerships, 0G ecosystem communities, and referrals provide extra benefits, such as rebates or promotional whitelist access. All promotional activities adhere to [regulatory guidelines](https://www.0gfoundation.ai/ai-alignment#disclaimer), and any reward or referral payments are conditional upon KYC eligibility. --- ## KYC Verification Guide Source: https://docs.0g.ai/node-sale/details/kyc-verification.md ## Introduction The 0G Alignment Node Portal requires users to complete a Know Your Customer (KYC) verification process to ensure secure and compliant participation. This comprehensive guide will walk you through each step of the verification process using Blockpass, our current KYC provider. :::info Additional KYC Providers Coming Soon Additional KYC provider options will be available soon to provide more flexibility for users. ::: --- ## Eligibility Requirements Before starting the KYC process, please ensure you meet the following requirements: ### Age Requirement You must be at least 18 years old to participate in the 0G Alignment Node Portal. ### Geographic Restrictions Due to regulatory requirements, users from the following countries and regions are **not eligible** to participate: **Restricted Countries:** - Belarus, the Central African Republic, The Democratic Republic of Congo, the Democratic People's Republic of Korea, Cuba, Iran, Libya, Russia, Somalia, Sudan, South Sudan, Venezuela, Yemen, Zimbabwe. **Restricted Regions:** - Ukraine: Crimea region, Donetsk People's Republic (DNR), Luhansk People's Republic (LNR), Kherson region, and Zaporizhia region :::important Geographic Restrictions If you reside in any of these restricted locations, you will not be able to complete the KYC process. This restriction is in place to comply with international regulations and sanctions. ::: --- ## Pre-Verification Checklist Before starting your KYC verification, ensure you have: - Valid government-issued ID - Recent proof of address document - Good lighting for selfie verification - Stable internet connection (disable VPN) - Desktop/laptop for wallet signing - Compatible browser (Chrome/Firefox recommended) - 15-20 minutes of uninterrupted time --- ## Getting Started
Video Guide Step by step video guide to complete the KYC process. ### Step 1: Start the KYC Process Go to the [KYC page](https://claim.0gfoundation.ai/kyc). Connect your wallet and click on "Start KYC" button. ### Step 2: Submit Documents Upload the required documents, complete the selfie verification. This submission can also be done on mobile for easier document upload.Make sure to close the mobile browser tab after submitting the documents before opening new session on desktop. ### Step 3: Complete Wallet Verification This step is critical and must be completed on desktop. Even if you submitted documents on mobile, you must complete this step on desktop so trigger the magic link again from portal (like the step 1), open the link in desktop browser and continue from there.
### Step 1: Connect Your Wallet Before beginning the KYC process, you'll need to connect your wallet to the 0G platform: 1. Navigate to the KYC section in your dashboard 2. Click **"Connect Wallet"** to initiate the verification process 3. Wait for the wallet connection to be confirmed 4. Click "Start KYC" to get started ![kyc-flow-1](/img/kyc-flow-1.png) ![kyc-flow-2](/img/kyc-flow-2.png) ### Step 2: Choose Your KYC Provider Currently, **Blockpass** is integrated as our primary KYC verification service - Select **"Blockpass (Recommended)"** - Click **"Continue"** to proceed ![kyc-flow-3](/img/kyc-flow-3.png) --- ## Creating Your Blockpass Account ### Email Registration Process 1. Enter your email address in the Blockpass modal 2. Choose whether to: - Create a new account, or - Use an existing Blockpass account 3. For new users: - A magic link will be sent to your email - Check your inbox and click the link, This will take you to the document upload interface :::tip Progress Saving If you've already started the process, Blockpass will remember your progress and allow you to continue where you left off. ::: --- ## Document Upload Process ![kyc-flow-4](/img/kyc-flow-4.png) ### Required Documents Checklist You'll need to provide the following three types of verification: ### 1. Government-Issued ID (Choose One) - Passport - National ID - Driving License ### 2. Proof of Address - Utility bill - Bank statement - Other supported documents ### 3. Liveness Verification - Selfie verification with liveness check ### Document Upload Guidelines ### For ID Documents: - **Preparation:** - Open your document to the data page - Find good lighting conditions - Clean your camera lens - **Capture Requirements:** - All four corners must be visible - Avoid glare and shadows - Ensure text is clear and readable - Document should fill most of the frame :::important Data Extraction Accuracy Even if the automatic data extraction shows incorrect information, proceed with submission. Our verification team will handle corrections during the manual review process. ::: ### For Address Proof: - Upload a document from the supported list - Ensure your current residential address is clearly visible - Document should be recent (typically within 3 months) ### For Selfie Verification: 1. **Setup:** - Find a well-lit room - Remove glasses if they cause glare - Position yourself at arm's length from camera 2. **Process:** - The system will auto-capture your face - Follow on-screen prompts: - Look straight ahead - Turn your head left when prompted - Turn your head right when prompted - Complete all requested movements
Cross-Device Flexibility One of Blockpass's convenient features is seamless cross-device compatibility: - Use the **"Email me a link"** button on any page - Continue your KYC process on any device - All progress is automatically saved - Switch between mobile and desktop as needed **Recommended Workflow:** 1. **Mobile:** Upload documents using your phone's camera 2. **Desktop:** Complete wallet verification for better experience 3. **Either:** Check status and make corrections
--- ## Wallet Verification (Critical Step) ### Desktop Strongly Recommended While you can complete most steps on mobile, **we strongly recommend using a desktop or laptop for wallet verification**. ### Benefits of Desktop Verification - Better signing experience - More stable connection to wallet extensions - Smoother completion of mandatory signing ### How to Switch to Desktop 1. **Complete initial steps on mobile (if preferred):** - Upload all documents - Complete selfie verification - Close the mobile browser tab 2. **Continue on desktop:** - Open Blockpass on your desktop browser - Log in using the same email address - Use magic link or password to access your account 3. **Resume verification:** - Select **"Register with document"** - Choose the same ID type you selected earlier - All your information will be pre-filled from the last session 4. **Complete wallet verification:** - Connect your wallet (MetaMask, WalletConnect, or Coinbase) - Sign the verification message when prompted - Confirm the signature in your wallet app :::important Mandatory Wallet Signing The wallet signing step is mandatory. Submissions without proper signing will NOT be approved due to KYC compliance requirements. ::: --- ## Final Submission ### Before Submitting: - Review all uploaded documents - Ensure wallet is properly connected and verified - Check that all sections show "completed" status ### To Submit: 1. Once all steps Completed 2. The **"Register"** button will become active 3. Click **"Register"** to submit for KYC verification 4. You'll see a confirmation screen, You can set password on this screen for future changes --- ## Verification Timeline | Stage | Timeframe | | --- | --- | | Initial Review | 24-36 hours | | Additional Checks (if needed) | 12-24 hours | | Final Approval | Email notification | ### What to Expect: - Email notifications at each stage - Clear feedback if any issues arise - Direct communication for any clarifications needed --- ## Handling Rejections If your KYC application is rejected, don't worry! Here's what to do: ### Steps to Resubmit: 1. **Check your email** for specific rejection reasons 2. **Log back in** using the same email address 3. **Navigate** to the rejected document section 4. **Update** only the required documents or information 5. **Resubmit** for re-verification --- ## Frequently Asked Questions
How can I ensure my documents are accepted on first submission? - Use good lighting and steady hands when taking photos - Ensure all documents show matching details - Use valid, non-expired identification - Clean your camera lens before capturing documents - Make sure all four corners of documents are visible - Avoid glare and shadows
What's the best way to complete the KYC process? - Complete the process in one session if possible - Have all documents ready before starting - Use Chrome, Safari or Firefox browsers for best compatibility - Disable VPN during verification - Use desktop for wallet signing, mobile for document photos - Don't log in to the same account on multiple devices simultaneously
Is my personal information secure? Yes, your KYC information is protected with: - End-to-end encryption for all uploads - Secure storage in compliance with GDPR - Information used only for verification purposes - No sharing with third parties without consent
My camera won't activate, what should I do? Check browser permissions for camera access and ensure your browser allows camera usage for the KYC site.
I can't connect my wallet, how do I fix this? Try using a different wallet or browser. Make sure pop-ups are enabled and you're using a desktop for the best wallet connection experience.
My document upload keeps failing, what's wrong? Check that your file size is under 10MB and you have a stable internet connection. Try refreshing the page and uploading again.
The verification message won't sign, what should I do? Switch to desktop and try a different browser. The wallet signing step works best on desktop computers.
My email link expired, how do I get a new one? Request a new magic link from the login page. Wait at least 5 minutes before requesting another link.
What are common reasons for KYC rejection? Common reasons for KYC rejection include: - Blurry or unclear document images - Expired identification documents - Address mismatch between documents - Incomplete wallet signature - Poor selfie quality or failed liveness check If your KYC application is rejected, check your email for specific rejection reasons and resubmit the corrected documents.
--- ## Need Help? **Discord Community:** Join our [Discord](https://discord.gg/0glabs) for peer support and quick answers from the team. **Support:** Contact us on Discord with screenshots and clear steps to reproduce any issues. --- **Disclaimer:** This guide is for informational purposes. KYC requirements may vary by jurisdiction. Always ensure you comply with your local regulations. --- ## How to Purchase Nodes Source: https://docs.0g.ai/node-sale/details/purchasing-nodes.md **Supported Blockchains and Payment Methods**: The sale was conducted in USDC on Arbitrum, with a live bridging gateway at checkout that supported multiple blockchains (ETH, Arbitrum, BNB) and tokens. All purchases require a compatible wallet, and the resulting node licenses are issued as non-transferable ERC-721 NFTs. ## Video Tutorial :::important Please note: Initially, the Public Sale was intended to use wETH on Arbitrum, but after the community’s feedback it used USDC on Arbitrum. Please note this correction to USDC on Arbitrum as the video says wETH. ::: Note that this video is for demonstrative purposes only, may not reflect exact details and have different prices or tokens than the actual sale. ## Step-by-Step Purchase Process: ### Step 1 - Go to https://node.0gfoundation.ai and connect your wallet ### Step 2 - Select the chain and token you want to purchase ### Step 3 - View the tiers available and purchase In total there are 32 available for purchase. If you hold a whitelisted address, the Tier that you are entitled to will be shown on the top. Sold out tiers will be moved to the bottom of the page. ### Step 4 - Set the quantity Start by inputting the number of node(s) that you will be purchasing. ### Step 5 - Input Promo Code (Optional) If you have a Promo Code, input before your purchase. The discount rate will be applied directly to your checkout price. Additionally, if you have already purchased a node, you can provide your wallet address as a referral promo code too! This will provide a 10% rebate to the referral, and 10% commission if they purchase successfully. ### Step 6 - Approve transaction Once you are confirmed on the final price, click the "Approve" button. You are then required to approve the transaction via your wallet. ### Step 7 - Complete purchase Continue by clicking "Purchase". You will need to confirm the transaction via your wallet. After confirming your purchase, you will receive a notification on the top right of the page to inform you of the successful purchase. --- ## Node Disclaimer Source: https://docs.0g.ai/node-sale/disclaimer.md PLEASE READ THE ENTIRETY OF THIS "LEGAL DISCLAIMER" SECTION CAREFULLY. NOTHING HEREIN CONSTITUTES LEGAL, FINANCIAL, BUSINESS, OR TAX ADVICE AND YOU ARE STRONGLY ADVISED TO CONSULT YOUR OWN LEGAL, FINANCIAL, TAX, OR OTHER PROFESSIONAL ADVISOR(S) BEFORE ENGAGING IN ANY ACTIVITY IN CONNECTION HEREWITH. NEITHER 0G FOUNDATION (“THE COMPANY”), ANY OF THE PROJECT CONTRIBUTORS WHO HAVE WORKED ON THE ZEROGRAVITY NETWORK (AS DEFINED HEREIN) OR ANY PROJECT TO DEVELOP THE ZEROGRAVITY NETWORK IN ANY WAY WHATSOEVER, ANY DISTRIBUTOR AND/OR VENDOR OF NODE LICENSE (OR SUCH OTHER RE-NAMED OR SUCCESSOR TICKER CODE OR NAME OF SUCH TOKENS) (THE “DISTRIBUTOR”), NOR ANY RELATED SERVICE PROVIDER SHALL BE LIABLE FOR ANY KIND OF DIRECT OR INDIRECT DAMAGE OR LOSS WHATSOEVER WHICH YOU MAY SUFFER IN CONNECTION WITH ACCESSING ANY MATERIAL RELATING TO NODE LICENSE NFT (THE TOKEN DOCUMENTATION) AVAILABLE ON THE WEBSITE AT https://www.0gfoundation.ai/ai-alignment (THE WEBSITE, INCLUDING ANY SUB-DOMAINS THEREON) OR ANY OTHER WEBSITES OR MATERIALS PUBLISHED OR COMMUNICATED BY THE COMPANY OR ITS REPRESENTATIVES FROM TIME TO TIME. 1. **Project purpose**: You agree that you are acquiring Node License NFT to participate in the ZeroGravity Network and to obtain services on the ecosystem thereon. The Company, the Distributor, and their respective affiliates would develop and contribute to the underlying source code for the ZeroGravity Network. The Company is acting solely as an arms’ length third party in relation to the Node License NFT distribution and is not acting in the capacity as a financial advisor or fiduciary of any person with regard to the distribution of Node License NFT. 2. **Eligibility**: To be eligible to use the Website (including services thereon) or participate in the Node License NFT distribution you must be at least eighteen (18) years of age or older. The Website, interface and services thereon is strictly NOT offered to persons or entities who reside in, are citizens of, are incorporated in, or have a registered office in any Restricted Territory, as defined below (any such person or entity from a Restricted Territory shall be a Restricted Person). If you are a Restricted Person, then do not attempt to access or use the Website. Use of a virtual private network (e.g., a VPN) or other means by Restricted Persons to access or use the Website, interface or services is prohibited. For the purpose of these Terms, Restricted Territory shall mean Belarus, Canada, Cuba, North Korea, Iran, Russia, Syria, the United States, the United Kingdom, Venezuela, Yemen, and specific regions in Ukraine and Russia, namely the Crimea region, Donetsk People’s Republic (DNR), Luhansk People’s Republic (LNR), as well as the Kherson and Zaporizhia regions. 3. **Validity of Token Documentation and Website**: Nothing in the Token Documentation or the Website constitutes any offer by the Company, the Distributor, or the ZeroGravity Network team to sell any Node License NFT (as defined herein) nor shall it or any part of it nor the fact of its presentation form the basis of, or be relied upon in connection with, any contract or purchase decision. Nothing contained in the Token Documentation or the Website is or may be relied upon as a promise, representation or undertaking as to the future performance of the ZeroGravity Network. The agreement between the Distributor (or any third party) and you, in relation to any distribution or transfer of Node License NFT, is to be governed only by the separate terms and conditions of such agreement. 4. **Deemed Representations and Warranties**: By accessing the Token Documentation or the Website (or any part thereof), you shall be deemed to represent and warrant to the Company, the Distributor, their respective affiliates, and the ZeroGravity Network team as follows: * in any decision to acquire any Node License NFT, you have not relied and shall not rely on any statement set out in the Token Documentation or the Website. * you shall at your own expense ensure compliance with all laws, regulatory requirements, and restrictions applicable to you (as the case may be). * you acknowledge, understand and agree that Node License NFT may have no value, there is no guarantee or representation of value or liquidity for Node License NFT, and Node License NFT is not an investment product nor is it intended for any investment purposes, speculative or otherwise. * none of the Company, the Distributor, their respective affiliates, and/or the ZeroGravity Network team shall be responsible for or liable for the value of Node License NFT, the transferability and/or liquidity of Node License NFT, and/or the availability of any market for Node License NFT through third parties or otherwise. 5. The Company, the Distributor, and the ZeroGravity Network team do not and do not purport to make, and hereby disclaims, all representations, warranties or undertaking to any entity or person (including without limitation warranties as to the accuracy, completeness, timeliness, or reliability of the contents of the Token Documentation or the Website, or any other materials published by the Company or the Distributor). To the maximum extent permitted by law, the Company, the Distributor, their respective affiliates, and service providers shall not be liable for any indirect, special, incidental, consequential, or other losses of any kind, in tort, contract, or otherwise (including, without limitation, any liability arising from default or negligence on the part of any of them, or any loss of revenue, income or profits, and loss of use or data) arising from the use of the Token Documentation or the Website, or any other materials published, or its contents (including without limitation any errors or omissions) or otherwise arising in connection with the same. Prospective acquirors of Node License NFT should carefully consider and evaluate all risks and uncertainties (including financial and legal risks and uncertainties) associated with the distribution of Node License NFT, the Company, the Distributor, and the ZeroGravity Network team. 6. **Node License NFT**: Node License NFT are designed to be utilized, and that is the goal of the Node License NFT distribution. In particular, it is highlighted that Node License NFT: * does not have any tangible or physical manifestation and does not have any intrinsic value/pricing (nor does any person make any representation or give any commitment as to its value). * is non-refundable, not redeemable for any assets of any entity or organization, and cannot be exchanged for cash (or its equivalent value in any other digital asset) or any payment obligation by the Company, the Distributor, or any of their respective affiliates. * does not represent or confer on the token holder any right of any form with respect to the Company, the Distributor (or any of their respective affiliates), or their revenues or assets, including without limitation any right to receive future dividends, revenue, shares, ownership right or stake, share or security, any voting, distribution, redemption, liquidation, proprietary (including all forms of intellectual property or license rights), right to receive accounts, financial statements or other financial data, the right to requisition or participate in shareholder meetings, the right to nominate a director, or other financial or legal rights, equivalent rights, or intellectual property rights, or any other form of participation in or relating to the ZeroGravity Network, the Company, the Distributor, and/or their service providers. * is not intended to represent any rights under a contract for differences or under any other contract the purpose or intended purpose of which is to secure a profit or avoid a loss. * is not intended to be a representation of money (including electronic money), payment instrument, security, commodity, bond, debt instrument, unit in a collective investment, managed investment scheme, or any other kind of financial instrument or investment. * is not a loan to the Company, the Distributor or any of their respective affiliates, is not intended to represent a debt owed by the Company, the Distributor, or any of their respective affiliates, and there is no expectation of profit nor interest payment. * does not provide the token holder with any ownership or other interest in the Company, the Distributor, or any of their respective affiliates. 7. Notwithstanding the Node License NFT distribution, users have no economic or legal right over or beneficial interest in the assets of the Company, the Distributor, or any of their affiliates after the token distribution. To the extent any secondary market or exchange for trading Node License NFT does develop, it would be run and operated wholly independently of the Company, the Distributor, and the distribution of Node License NFT. Neither the Company nor the Distributor will create such secondary markets nor will either entity act as an exchange for Node License NFT. 8. **English language**: The Token Documentation and the Website may be translated into a language other than English for reference purpose only and in the event of conflict or ambiguity between the English language version and translated versions of the Token Documentation or the Website, the English language versions shall prevail. You acknowledge that you have read and understood the English language version of the Token Documentation and the Website. 9. **No Distribution**: No part of the Token Documentation or the Website is to be copied, reproduced, distributed, or disseminated in any way without the prior written consent of the Company or the Distributor. By attending any presentation on this Token Documentation or by accepting any hard or soft copy of the Token Documentation, you agree to be bound by the foregoing limitations. --- ## Node Sale FAQ Source: https://docs.0g.ai/node-sale/faq.md :::note The public 0G AI Alignment Node Sale was held in November 2024 and is now closed, and 0G Mainnet launched in September 2025. This page is kept for reference. ::: ## General ### Where were AI Alignment Nodes sold? The sale ran at https://node.0gfoundation.ai/ and has concluded. ### How did I purchase AI Alignment Nodes? See the step by step guide [here](/node-sale/details/purchasing-nodes). ### Who could participate in the Node Sale? The 0G AI Alignment Node Sale was open to community members in eligible regions who met the necessary criteria. Please review all disclaimers and important details regarding the 0G Node Sale by visiting our disclaimer [here](https://www.0gfoundation.ai/ai-alignment#disclaimer). Only persons who met the requirements for the sale were allowed to participate. KYC is required from the purchaser before any receipt of rewards. ### Were Whitelist and Public Allocations Separate? The whitelist allocation was independent and was not rolled over to the public sale. The **Whitelist Sale** opened on November 11, 2024, at 12 PM UTC. It was denominated in USDC on Arbitrum, and only whitelisted participants could purchase nodes during that phase. The **Public Sale** opened on November 13, 2024, at 12 PM UTC, was denominated in USDC on Arbitrum, and was open to all users, subject to geographic and regulatory restrictions. Please see our disclaimer for more information. ![0g-node-sale-timeline-1600x900px](https://github.com/user-attachments/assets/dd6746d7-a102-43f3-9a1f-ae33d0ca7f72) ### What price was the sale pegged to? Both the Whitelist and Public Sales were denominated in USDC on Arbitrum. Node pricing was pegged to a snapshot price of wETH of $3,130. ### When can I operate my node? Node operations began after the mainnet launch, which took place in September 2025. License holders received further instructions for operation and delegation options if preferred. ### How Do Rewards for Alignment Nodes Compare with Other Nodes? Alignment Nodes are expected to offer higher reward rates due to their unique responsibilities, limited supply, and operational requirements compared to storage or validator nodes. ### Are Multiple NFTs Supported per Server? Yes, users may operate multiple NFTs on a single server, with allowances for connecting and managing several nodes under one setup. ## Whitelist & Node Sale ### What is the whitelist (WL)?​ Whitelist is a pre-approved list of participants who are given exclusive access to certain privileges during a sale event. This system is used to reward and incentivize key contributors, partners, or early supporters of a project. ### Does entering the whitelist guarantee that I can definitely purchase a node?​ The whitelist guaranteed an allocation during the Whitelist sale period (starting November 11, 2024). If no purchase was made within that period, the allocation was released. ### How did people join the whitelist?​ Community members and ecosystem participants were eligible for whitelist allocations. Spots were announced on 0G X and Discord, and could also be requested through the whitelist form [here](https://docs.google.com/forms/d/e/1FAIpQLScZSiIn3WBEdztzCObFBnLa0c6f1YoRwlN_eI8NxGPuG4w-zg/viewform). The form is closed now that the sale has concluded. ## Payment & Licenses ### What payment methods were accepted for purchasing a node?​ The nodes were priced in USDC for both the Whitelist Sale and Public Sale, both on Arbitrum. To facilitate payment for users on different chains, the AI Alignment Node Sale accepted multiple tokens across multiple networks through a live bridging aggregator that accepted multichain payment including but not limited to BTC, ETH, ARB, SOL, etc. More info [here](https://docs.li.fi/list-chains-bridges-dex-aggregators-solvers). ### How were the node licenses distributed?​ After the node sale period ended, node licenses were distributed as an NFT to the purchase wallet of the user. ### What did participants receive from the node sale?​ Participants received a soulbound NFT (ERC-721) which represents their Node License. The NFTs can be minted and transferred to your wallet via claim.0gfoundation.ai. Nodes can be operated now that 0G Mainnet is live. ### Were the NFTs transferable? The Alignment Node license gives buyers lifetime access. The NFTs were non-transferable for the first year after the node sale. ## Node Operations ### What are the hardware requirements?​ 0G Foundation’s AI Alignment nodes are designed for adoption - they can be run on community member's laptops, desktops, mobiles, or even on cloud instances. As for device requirements, the configuration needed is very minimal: - 64MB RAM - 1 x86 CPU Core @2.1GHz - 10GB Disk Space - 10Mbps Internet Connection ### When can I begin operating my node?​ AI Alignment utility went live in 2025, after the 0G Mainnet launch. ### How many nodes could I purchase?​ The number of purchasable nodes was capped per tier. Please refer to the [Node Sale Tier documentation](https://docs.google.com/spreadsheets/d/16dgdbrs0LA_mSSYB7cSEWmQPMJvok0FjqAHX-nLxEzs/edit?gid=2031834824#gid=2031834824) for reference. ### How do I run a node? Is it complicated?​ Running a node can be quite straightforward and easy, typically involving just a few steps. Here's a video tutorial to guide you through the process: If you prefer not to manage the node yourself, you can delegate to other node operators with a single click through our explorer. See the [AI Alignment Node user guide](/node-sale/ai-alignment-node-user-guide) for the delegation steps. ### Was the sale accessible from other platforms?​ Both the Public and Whitelist sales ran [here](https://node.0gfoundation.ai/) except for Partnered Launchpads, whose front ends were on 0G Partners' websites. ### What happened to any unsold node rewards? Rewards from unsold nodes were reallocated to the sold node runners. ### What is your tokenomics? ![token table-v4 (1)](https://github.com/user-attachments/assets/125b812b-cd4f-4f8f-bb95-a1933d70b84b) ![token pie chart-v4](https://github.com/user-attachments/assets/814b1112-7ed6-47de-bf95-582cd55569d9) ### What is the % unlocked at TGE? 33% of node rewards will be initially claimable on TGE. In order to encourage long term participation in the 0G ecosystem, there will be a penalty based on duration in which a participant chooses to receive this initial reward. The remaining 67% of alignment rewards are linearly unlocked (daily) over 36 months. This penalty mechanism is subject to community vote, further showcasing the "community first approach" of 0G. ### When is KYC required? How is it conducted? KYC is required before claiming rewards. It will be provided by a third-party provider. No refund will be offered if the node purchaser does not meet KYC requirements. ### How many nodes could each buyer purchase? Each individual could purchase up to a certain amount of nodes per tier. See [here](https://docs.google.com/spreadsheets/d/16dgdbrs0LA_mSSYB7cSEWmQPMJvok0FjqAHX-nLxEzs/edit?gid=2031834824#gid=2031834824) for the caps per tier. ### What happened to unsold nodes? Unsold alignment node NFT licenses were burned. The rewards from the unsold nodes were re-allocated to the sold verified node buyers. ### Which launchpad partners worked on the 0G Foundation Node Sale? ![Launchpads-1600x900px](https://github.com/user-attachments/assets/4b4d98d8-c480-407d-89fa-530e66fe2328) --- ## Eligibility & Disclaimer Source: https://docs.0g.ai/node-sale/intro/eligibility.md - **Whitelist Access**: Community engagement, role-based eligibility, and participation in 0G’s Discord or X channels were the pathways to a whitelist spot. Joining the whitelist did not guarantee a purchase; it only ensured allocation access during the whitelist phase. - **Special Roles and Partnerships**: Selected community members, project partners, and Key Opinion Leaders (KOLs) received additional access or promotional privileges, subject to guidelines for eligible users and without guarantees for resale or transferability of whitelist spots. ## Disclaimer​ Please review the full details and terms of the 0G Node Sale by visiting our [disclaimer](https://www.0gfoundation.ai/ai-alignment#disclaimer). --- ## Introduction Source: https://docs.0g.ai/node-sale/intro.md :::note The public 0G AI Alignment Node Sale was held in November 2024 and is now closed, and 0G Mainnet launched in September 2025. These pages are kept for reference. For running or delegating a node today, see the [AI Alignment Node user guide](/node-sale/ai-alignment-node-user-guide). ::: ## Purpose and Benefits of the 0G AI Alignment Node Sale The objective of 0G Foundation: The 0G Foundation’s node sale was designed to create a trust layer for AI that operates transparently, safely, and under community influence. Centralized AI structures may lack these attributes, creating potential risks for data integrity and security. The 0G Foundation’s goal is to develop AI as a public good, fostering an ecosystem that prioritizes transparency and reduces reliance on central authorities, making it suitable for broad public utility. ## What is an AI Alignment Node? Alignment nodes provide the key utility of monitoring whether the other kinds of decentralized nodes in the 0G network - validator nodes, storage nodes, security nodes - faithfully follow network protocols. To start, the nodes will have certain utility, and in the near future, AI Alignment Nodes will have additional utility to monitor on-chain AI model drift and to ensure that 0G’s on-chain AI is behaving as intended. To sustain the node utility operation and allow the network to be further secured, Alignment Node owners may receive a portion of the fees collected by the network by operating the nodes and contributing work to the 0G network. Node sale participants and stakers (i.e., long term believers who secure the ecosystem) may get additional rewards from the 0G ecosystem over time. The 0G node sale was a launch that enabled the community to participate on an equal playing field with entry points within multiple tiers. ## Why Run a Node? Running a node on the 0G network offers participants a chance to directly contribute to the growth and security of our decentralized AI ecosystem. Nodes are the backbone of our network, enabling the following: - **Decentralization**: Ensure the network remains decentralized and resilient. - **Network Security**: Enhance the security and reliability of the network by verifying transactions. - **AI Processing Power**: Support AI computations, thereby contributing to the network's ability to deliver on-chain AI services. - **Reward Opportunities**: Node operators can earn rewards in the form of native tokens or other incentives for their contribution to the network. ## What are the specific use cases for AI Alignment Nodes? - **Protocol Monitoring**: Ensuring that validator, storage, and security nodes comply with network protocols. - **AI Model Monitoring**: Tracking AI model alignment and checking for any unintended behavior. - **Network Security**: Safeguarding the ecosystem by flagging deviations and ensuring consistent ethical standards. - **Economic and Governance Roles**: Node holders may earn rewards and participate in governance decisions, influencing the network’s direction. --- ## Node Holder Benefits Source: https://docs.0g.ai/node-sale/intro/node-holder-benefits.md As an alignment node operator in 0G's ecosystem, users have the opportunity to earn up to 15% of the total 0G ecosystem supply allocated over the next 3 years by helping to secure the network. Nodes are rewarded for assisting in checking and verifying the correct behavior of storage, DA, and serving nodes within the network, playing a crucial role in ensuring data integrity for the AI and other supported workloads. Additional rewards will be provided from 0G’s vibrant and growing ecosystem as a coordinated effort to maintain the AI integrity and security of the platform. The Alignment Node sale offers holders the chance to join the network and contribute to the development and security of a decentralized ecosystem for the largest collection of decentralized AI computing and data processing power, without requiring every regular user to be prepared for intensive computational tasks from day one. --- ## Sale Structure & Timeline Source: https://docs.0g.ai/node-sale/intro/sale-structure.md ## Sale Phases The sale was structured into two phases: - **Whitelist Sale**: The Whitelist Sale opened on November 11, 2024, at 12 PM UTC and stayed open for two days. It was denominated in USDC on Arbitrum, and only whitelisted participants could purchase nodes during this phase. - **Public Sale**: The Public Sale opened on November 13, 2024, at 12 PM UTC, was denominated in USDC on Arbitrum, and was open to all users, subject to geographic and regulatory restrictions. Please see our disclaimer for more information. ![0g-node-sale-timeline-1600x900px (1)](https://github.com/user-attachments/assets/395a233d-d39f-4d3f-a7cc-9244dcb6df6a) ## Tier Pricing The node sale was segmented into 32 pricing tiers, beginning at 0.05 ETH per node, allowing for varied entry points that catered to diverse participant levels. While pegged to an ETH snapshot price of $3,130, both sales were conducted in USDC on Arbitrum. See [here](https://docs.google.com/spreadsheets/d/16dgdbrs0LA_mSSYB7cSEWmQPMJvok0FjqAHX-nLxEzs/edit?gid=2031834824#gid=2031834824) for more details. ![Node Sale Table](https://github.com/user-attachments/assets/a3bedcd9-41ea-45a7-a804-4309b971881c) --- ## AI Alignment Node Sale Source: https://docs.0g.ai/node-sale/node-sale-index.md In this section, learn more about the 0G Foundation AI Alignment Node Sale. - [What is the 0G Foundation AI Alignment Node Sale?](/node-sale/intro) - [Why should I participate?](/node-sale/intro/node-holder-benefits) - [Who can participate?](/node-sale/intro/eligibility) - [How do I purchase nodes?](/node-sale/details/purchasing-nodes) - [Frequently Asked Questions](/node-sale/faq) ![Launchpads-1600x900px](https://github.com/user-attachments/assets/f034673b-d04f-4006-893c-51a5e9a4d172) --- ## 0G Blog Source: https://docs.0g.ai/resources/blog.md Visit the 0G Blog at https://0g.ai/blog for the latest updates and announcements. --- ## Glossary Source: https://docs.0g.ai/resources/glossary.md A comprehensive list of technical terms used throughout the 0G documentation. ## A **AI Agent**: An autonomous software program that can perceive its environment, make decisions, and take actions to achieve specific goals. **AVS (Actively Validated Services)**: Services that require active validation from operators, commonly used in restaking protocols like EigenLayer and Babylon. ## C **Chain**: In the context of 0G, refers to the 0G blockchain that serves as the foundational layer for transactions and smart contracts. **Compute Network**: The distributed network of nodes that provide computational resources for AI workloads including inference and training. ## D **DA (Data Availability)**: A layer that ensures data required by blockchain applications is available when needed, crucial for scalability and security. **Decentralized Storage**: A storage system that distributes data across multiple nodes rather than relying on centralized servers. ## E **ERC-721**: The standard interface for non-fungible tokens (NFTs) on Ethereum and EVM-compatible chains. **ERC-7857**: An extension of ERC-721 that adds support for encrypted metadata, enabling secure transfer of AI agents as NFTs. **ERC-8004**: The "Trustless Agents" standard defining on-chain registries (Identity, Reputation, Validation) that make AI agents discoverable, interoperable, and trusted across the ecosystem. 0G officially supports ERC-8004. See [ERC-8004 Trustless Agents](/developer-hub/building-on-0g/agentic-id/erc8004). **Erasure Coding**: A data protection method that breaks data into fragments and encodes it with redundant pieces to ensure recovery even if some parts are lost. ## I **Inference**: The process of using a trained AI model to make predictions or decisions based on new input data. **Agentic ID** (formerly **INFT**, "Intelligent Non-Fungible Token"): NFTs that can encapsulate AI agents with their intelligence and capabilities intact. Compatible with [ERC-8004](/developer-hub/building-on-0g/agentic-id/erc8004) for cross-ecosystem discoverability. See [Agentic IDs](/concepts/agentic-id). ## M **Modular Blockchain**: A blockchain architecture where different functions (consensus, execution, data availability) are separated into specialized layers. ## O **Oracle**: In the context of Agentic IDs (formerly INFTs), a service that verifies the integrity of metadata transfers using either TEE or ZKP technology. ## P **Precompile**: Built-in functions in a blockchain that are implemented at the protocol level for optimal performance. **Proof of Random Access (PoRA)**: 0G's consensus mechanism that ensures data availability by requiring nodes to prove they can access random data samples. ## Q **Quorum**: A minimum number of nodes required to reach consensus on a decision in a distributed system. ## R **RaaS (Rollup as a Service)**: Platforms that provide infrastructure and tools to easily deploy and manage blockchain rollups. **Rollup**: A scaling solution that processes transactions off the main chain while posting transaction data back to it. ## S **Sharding**: A scaling technique that divides a network into smaller parts (shards) to process transactions in parallel. **Storage Node**: A node in the 0G network that stores and serves data to the network. ## T **TEE (Trusted Execution Environment)**: A secure area of a processor that ensures code and data loaded inside are protected with respect to confidentiality and integrity. **Testnet**: A test network that mimics the main network but uses test tokens, allowing developers to experiment without real value at risk. ## V **Validator Node**: A node that participates in consensus by validating transactions and proposing new blocks. ## W **Web3**: The vision of a decentralized internet built on blockchain technology, emphasizing user ownership and control. ## Z **Zero Gravity (0G)**: The name representing the weightless state where transactions and data exchanges occur effortlessly in the 0G ecosystem. **Zero-Knowledge Proof (ZKP)**: A cryptographic method where one party can prove to another that a statement is true without revealing any information beyond the validity of the statement. --- *This glossary is continuously updated as the 0G ecosystem evolves. If you encounter a term not listed here, please contribute by submitting a pull request to our [documentation repository](https://github.com/0gfoundation/0g-doc).* --- ## How to Contribute Source: https://docs.0g.ai/resources/how-to-contribute.md We welcome and encourage you to contribute to our open-source project! Whether you're a seasoned developer or new to the community, your participation helps us push decentralized AI forward. Every contribution, no matter the size, makes a difference. Please check out our [Contribution Guidelines](https://github.com/0gfoundation/0g-doc/blob/main/CONTRIBUTING.md) to learn more about our criteria and how you can get involved. All submissions will be reviewed by a team member to ensure they meet our standards. Let's build the future of decentralized AI together. --- ## Security Policy Source: https://docs.0g.ai/resources/security.md At 0G, we prioritize the security and integrity of our platform. Our commitment to security is reflected in our rigorous audit processes and our active bug bounty program. ## Audits We regularly conduct thorough security audits of our smart contracts, protocols, and infrastructure to ensure the highest level of security for our users. ### Recent Audits | Date | Auditor | Scope | Report | |------|---------|-------|--------| | Aug 2024 - Sept 2024 | Halborn | 0G Storage | [Report](https://github.com/0gfoundation/0g-doc/blob/main/audit/Halborn%200G%20Storage%20Node%20Audit.pdf) | | Aug 2024 | Zellic | 0G Storage and 0G DA | [Report](https://github.com/0gfoundation/0g-doc/blob/main/audit/Zellic%200G%20Storage%20and%200G%20DA%20Audit.pdf) | | Aug 2025 | Octane | 0G Chain | [Report](https://drive.google.com/file/d/1SgL-PDL_8jzDTUMQ9pO28OQVCP2IeqHR/view) | For a complete list of our audits and their detailed reports, please visit our [GitHub repository](https://github.com/0gfoundation/0g-doc/tree/main/audit). ## [0G Labs Bug Bounty Program with Hackenproof](https://hackenproof.com/programs/0g-labs-smart-contracts) At 0G, we believe in the power of **community-driven security**. Our bug bounty program invites security researchers and developers to help us identify and resolve potential vulnerabilities, ensuring the robustness of our systems. ### Scope of the Bug Bounty Program Our bug bounty program covers: - Smart Contracts - Infrastructure - Protocol ## Focus Area ### In-Scope Vulnerabilities: We are interested in vulnerabilities that result in incorrect behavior of the smart contract and could lead to unintended functionality, including: - Stealing or loss of funds - Unauthorized transactions - Transaction manipulation - Attacks on logic (behavior that deviates from the intended business logic) - Reentrancy attacks - Reordering transactions - Overflows and underflows ### Out-of-Scope Vulnerabilities: The following are out of scope for the bug bounty program: - Theoretical vulnerabilities without proof or demonstration - Old compiler versions - Unlocked compiler version - Vulnerabilities in imported contracts - Code style guide violations - Redundant code - Gas optimizations - Best practice issues - Vulnerabilities exploitable through front-run attacks only Additionally, the following contracts are out of scope for 0g-storage-contract: - `cashier` - `token` - `reward/OnePoolReward` - `reward/ChunkDecayReward` - `uploadMarket` - `utils/Exponent.sol` ### Rewards Rewards are based on the severity of the discovered vulnerability: | Severity | Reward Range | |----------|--------------| | Critical | $35,000 | | High | $8000 | | Medium | $2000 | | Low | $500 | ### Program Rules - Avoid using web application scanners for automatic vulnerability searching which generates massive traffic - Make every effort not to damage or restrict the availability of products, services, or infrastructure - Avoid compromising any personal data, interruption, or degradation of any service - Don’t access or modify other user data, localize all tests to your accounts - Perform testing only within the scope - Don’t exploit any DoS/DDoS vulnerabilities, social engineering attacks, or spam - Don’t spam forms or account creation flows using automated scanners - In case you find chain vulnerabilities we’ll pay only for vulnerability with the highest severity. - Don’t break any law and stay in the defined scope - Any details of found vulnerabilities must not be communicated to anyone who is not a HackenProof Team or an authorized employee of this Company without appropriate permission ### Disclosure Guidelines :::important - Do not discuss this program or any vulnerabilities (even resolved ones) outside of the program without express consent from the organization - No vulnerability disclosure, including partial is allowed for the moment. - Please do NOT publish/discuss bugs ::: ### Eligibility and Coordinated Disclosure We are happy to thank everyone who submits valid reports which help us improve the security. However, only those that meet the following eligibility requirements may receive a monetary reward: - You must be the first reporter of a vulnerability. - The vulnerability must be a qualifying vulnerability - Any vulnerability found must be reported no later than 24 hours after discovery and exclusively through hackenproof.com - You must send a clear textual description of the report along with steps to reproduce the issue, include attachments such as screenshots or proof of concept code as necessary. - You must not be a former or current employee of us or one of its contractors. - ONLY USE the EMAIL under which you registered your HackenProof account (in case of violation, no bounty can be awarded) - Provide detailed but to-the point reproduction steps We look forward to working with the community to enhance 0G's security! --- ## 0G Whitepaper Source: https://docs.0g.ai/resources/whitepaper.md Download PDF --- ## Archival Node Source: https://docs.0g.ai/run-a-node/archival-node.md --- Running an Archival node for the **0G Galileo Testnet** means providing complete historical data storage and access for the network, maintaining the full blockchain history and state. :::info **What You'll Need** - Linux system with sufficient disk space for archive data - `lz4` compression tool installed - Public IP address for node connectivity - Stable internet connection ::: ## Hardware Requirements | Component | Requirement | |------------|-------------| | Memory | 64 GB | | CPU | 8 cores | | Disk | Large NVME SSD (for full archive data) | | Bandwidth | 100 MBps for Download / Upload | ## Prerequisites ### Required Files 1. **Node Package**: [galileo-archive.tar.gz](/binaries/galileo-archive.tar.gz) ### System Requirements - Linux system with sufficient disk space for archive data - `lz4` compression tool installed - Public IP address for node connectivity ## Setup Guide ### 1. Download Node Package Download the node package: [galileo-archive.tar.gz](/binaries/galileo-archive.tar.gz) ### 2. Extract Node Package Unzip the file to your home directory ## Deployment Steps ### 1. Copy Files and Set Permissions ```bash cd galileo-v1.2.0 cp -r 0g-home {your data path} sudo chmod 777 ./bin/geth sudo chmod 777 ./bin/0gchaind ``` ### 2. Initialize Geth ```bash ./bin/geth init --state.scheme=hash --db.engine=pebble --datadir /{your data path}/0g-home/geth-home ./genesis.json ``` ### 3. Initialize 0gchaind with Temporary Directory ```bash ./bin/0gchaind init {node name} --home /{your data path}/tmp ``` ### 4. Copy Node Files to 0gchaind Home ```bash cp /{your data path}/tmp/data/priv_validator_state.json /{your data path}/0g-home/0gchaind-home/data/ cp /{your data path}/tmp/config/node_key.json /{your data path}/0g-home/0gchaind-home/config/ cp /{your data path}/tmp/config/priv_validator_key.json /{your data path}/0g-home/0gchaind-home/config/ ``` ### 5. Start 0gchaind ```bash cd galileo-v1.2.0 nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.chain-spec devnet \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt-secret.hex \ --chaincfg.kzg.implementation=crate-crypto/go-kzg-4844 \ --chaincfg.block-store-service.enabled \ --chaincfg.node-api.enabled \ --chaincfg.node-api.logging \ --chaincfg.node-api.address 0.0.0.0:3500 \ --pruning=nothing \ --home /{your data path}/0g-home/0gchaind-home \ --p2p.seeds 85a9b9a1b7fa0969704db2bc37f7c100855a75d9@8.218.88.60:26656 \ --p2p.external_address {your node ip}:26656 > /{your data path}/0g-home/log/0gchaind.log 2>&1 & ``` ### 6. Start Geth ```bash cd galileo-v1.2.0 nohup ./bin/geth \ --config geth-archive-config.toml \ --nat extip:{your node ip} \ --bootnodes enode://de7b86d8ac452b1413983049c20eafa2ea0851a3219c2cc12649b971c1677bd83fe24c5331e078471e52a94d95e8cde84cb9d866574fec957124e57ac6056699@8.218.88.60:30303 \ --datadir /{your data path}/0g-home/geth-home \ --state.scheme=hash \ --gcmode archive \ --networkid 16602 > /{your data path}/0g-home/log/geth.log 2>&1 & ``` ### 7. Verify Setup Check the logs to ensure the node is running properly: ```bash # Check Geth logs tail -f /{your data path}/0g-home/log/geth.log # Check 0gchaind logs tail -f /{your data path}/0g-home/log/0gchaind.log ``` :::success **Success Indicators** - 0gchaind should show "Committed state" messages - Geth should show archive mode synchronization - No error messages in either log ::: ## Important Configuration Notes ### Variables to Replace - `{your data path}`: Your chosen data directory path - `{node name}`: Your chosen node name - `{your node ip}`: Your server's public IP address ### Directory Structure After setup, your directory structure should look like: ```text {your data path}/ └── 0g-home/ ├── geth-home/ ├── 0gchaind-home/ │ ├── config/ │ │ ├── node_key.json │ │ └── priv_validator_key.json │ └── data/ │ └── priv_validator_state.json └── log/ ├── 0gchaind.log └── geth.log ``` ### Network Ports Ensure the following ports are open: - **26657**: 0gchaind RPC - **26656**: 0gchaind P2P - **3500**: Node API - **30303**: Geth network ## Archive Node Benefits Archive nodes provide several key benefits to the 0G network: - **Complete Historical Data**: Full access to all historical blockchain data and state - **Enhanced Query Capabilities**: Support for complex historical queries and analytics - **Network Resilience**: Backup and redundancy for the network's historical data - **Developer Support**: Essential for applications requiring historical blockchain data :::warning **Storage Requirements** Archive nodes require significantly more storage space than regular nodes as they maintain the complete blockchain history. Ensure adequate disk space before setup. ::: --- ## Community Docker Repository Source: https://docs.0g.ai/run-a-node/community-docker-repo.md --- This section provides a list of Docker images 🐳 for 0G DA from the community. For instructions on running 0G nodes via binary installation, please visit the node pages directly. For most users, Docker offers the simplest method to get 0G nodes up and running. Docker is a platform for containerization, allowing 0G nodes to operate in an isolated environment. This approach enables you to run 0G nodes on your system without needing to install and configure all the necessary dependencies manually. Most of the officially endorsed 0G Docker implementations can be found under the documentation page for each 0G node type. Below is a list of community-maintained Docker images for 0G DA. Please note that these images are not officially endorsed by 0G, and users should proceed with caution. ## All Node Types [Ember Stake](https://docs.emberstake.xyz/networks/zero-gravity/nodes-guide/getting-started) --- ## Data Availability Node Source: https://docs.0g.ai/run-a-node/da-node.md While there are various approaches to running a DA (Data Availability) node, this guide outlines our recommended method and the necessary hardware specifications. DA Nodes perform the core functions of verifying, signing, and storing encoded blob data. To operate effectively, your DA signer needs to run a DA node to verify encoded blob data, sign it, and store it for future farming and rewards. Currently, to run a DA Node on Testnet, users must stake 10 OG tokens. These can be obtained through our [faucet](https://faucet.0g.ai/) or via rewards from running Storage Nodes or Validator Nodes. You can also reach out to our technical moderators on [Discord](https://discord.com/invite/0glabs). ## Hardware Requirements | Node Type | Memory | CPU | Disk | Bandwidth | Additional Notes | |-----------|--------|-----|------|-----------|------------------| | DA Node | 16 GB | 8 cores | 1 TB NVMe SSD | 100 MBps | For Download/Upload | ## Standing up a DA Node and DA Signer **1. Clone the DA Node Repo:** ```bash git clone https://github.com/0gfoundation/0g-da-node.git cd 0g-da-node ``` **2. Generate BLS Private Key (if needed):** If you don't have a BLS private key, generate one: ```bash cargo run --bin key-gen ``` Keep the generated BLS private key secure. **3. Set up config.toml:** 1. Create a configuration file named `config.toml` in the project root directory. 2. Add the following content to the file, adjusting values as needed: ```toml log_level = "info" data_path = "/data" # path to downloaded params folder encoder_params_dir = "/params" # grpc server listen address grpc_listen_address = "0.0.0.0:34000" # chain eth rpc endpoint eth_rpc_endpoint = "https://evmrpc-testnet.0g.ai" # public grpc service socket address to register in DA contract # ip:34000 (keep same port as the grpc listen address) # or if you have dns, fill your dns socket_address = ":34000" # data availability contract to interact with da_entrance_address = "0x857C0A28A8634614BB2C96039Cf4a20AFF709Aa9" # testnet config # deployed block number of da entrance contract start_block_number = 940000 # testnet config # signer BLS private key signer_bls_private_key = "" # signer eth account private key signer_eth_private_key = "" # miner eth account private key, (could be the same as `signer_eth_private_key`, but not recommended) miner_eth_private_key = "" # whether to enable data availability sampling enable_das = "true" ``` Make sure to fill in the `signer_bls_private_key`, `signer_eth_private_key`, and `miner_eth_private_key` fields with your actual private keys. **4. Build and Start the Docker Container:** ```bash docker build -t 0g-da-node . docker run -d --name 0g-da-node 0g-da-node ``` **5. Verify the Node is Running** On the first run, the DA node will register the signer information in the DA contract. You can monitor the console output to ensure the node is running correctly and has successfully registered. ### Node Operations As a DA node operator, your node will perform the following tasks: - Encoded blob data verification - Signing of verified data - Storing blob data for further farming - Receiving rewards for these operations ### Troubleshooting - If you encounter any issues, check the console output for error messages. - Ensure that the ports specified in your `config.toml` file are not being used by other applications. - Verify that you have the latest stable version of Rust installed. - Make sure your system meets the minimum hardware requirements. ### Conclusion You have now successfully set up and run a 0g DA node as a DA Signer. For more advanced configuration options and usage instructions, please refer to the [Official GitHub repository](https://github.com/0gfoundation/0g-da-node). Remember to keep your private keys secure and regularly update your node software to ensure optimal performance and security. ## Step 1: Clone and Build the Repository 1. Install dependencies: ```bash sudo apt-get update && sudo apt-get install clang cmake build-essential pkg-config libssl-dev protobuf-compiler llvm llvm-dev ``` 2. Clone the repository and checkout the specific version: ```bash git clone https://github.com/0gfoundation/0g-da-node.git cd 0g-da-node ``` 3. Build the project: ```bash cargo build --release ``` 4. Download necessary parameters: ```bash ./dev_support/download_params.sh ``` ## Step 2: Generate BLS Private Key (if needed) If you don't have a BLS private key, generate one: ```bash cargo run --bin key-gen ``` **Keep the generated BLS private key secure.** ## Step 3: Configure the Node 1. Create a configuration file named `config.toml` in the project root directory. 2. Add the following content to the file, adjusting values as needed: ```toml log_level = "info" data_path = "./db/" # path to downloaded params folder encoder_params_dir = "params/" # grpc server listen address grpc_listen_address = "0.0.0.0:34000" # chain eth rpc endpoint eth_rpc_endpoint = "https://evmrpc-testnet.0g.ai" # public grpc service socket address to register in DA contract # ip:34000 (keep same port as the grpc listen address) # or if you have dns, fill your dns socket_address = ":34000" # data availability contract to interact with da_entrance_address = "0x857C0A28A8634614BB2C96039Cf4a20AFF709Aa9" # testnet config and see testnet page for the latest info # deployed block number of da entrance contract start_block_number = 940000 # testnet config # signer BLS private key signer_bls_private_key = "" # signer eth account private key signer_eth_private_key = "" # miner eth account private key, (could be the same as `signer_eth_private_key`, but not recommended) miner_eth_private_key = "" # whether to enable data availability sampling enable_das = "true" ``` Make sure to fill in the `signer_bls_private_key`, `signer_eth_private_key`, and `miner_eth_private_key` fields with your actual private keys. ## Step 4: Run the Node Start the 0g DA node using the following command: ```bash ./target/release/server --config config.toml ``` This will start the node using the configuration file you created. ## Step 5: Verify the Node is Running On the first run, the DA node will register the signer information in the DA contract. You can monitor the console output to ensure the node is running correctly and has successfully registered. ## Node Operations As a DA node operator, your node will perform the following tasks: - Encoded blob data verification - Signing of verified data - Storing blob data for further farming - Receiving rewards for these operations ## Troubleshooting - If you encounter any issues, check the console output for error messages. - Ensure that the ports specified in your `config.toml` file are not being used by other applications. - Verify that you have the latest stable version of Rust installed. - Make sure your system meets the minimum hardware requirements. ## Conclusion You have now successfully set up and run a 0g DA node as a DA Signer. For more advanced configuration options and usage instructions, please refer to the [Official GitHub repository](https://github.com/0gfoundation/0g-da-node). Remember to keep your private keys secure and regularly update your node software to ensure optimal performance and security. ## Overview The DASigners contract is an interface through which Solidity contracts can interact with the 0G chain module DASigners. It is registered as a precompiled contract, similar to other precompiled EVM extensions. ## Becoming a DA Signer To become a DA signer, you must meet the following requirements: 1. Delegation Requirement: To become a signer, an address must receive enough delegations, equivalent to at least the TokensPerVote amount of OG tokens (30 tokens per vote in the testnet), registered in the DASigners module. 2. Node Operation: Each signer needs to run a DA (Data Availability) node that verifies blob encoding and generates BLS signatures for signed blobs. 3. Registration: Signers must register their information using the registerSigner function. This includes providing their address, node socket address, BLS public key, and a signature signed by their BLS private key. 4. Epoch Participation: Signers must submit a registration message (using the registerNextEpoch function) with a signature for each epoch they wish to participate in. This is necessary for joining quorums in the next epoch. 5. Voting Power: Each signer’s voting power is determined by the number of tokens delegated to them. Signers can have up to 1024 votes, and the votes are distributed randomly into quorums. 6. Quorum Responsibilities: Each signer in a quorum is responsible for validating, signing, and storing a specific row of encoded blob data during an epoch. ## Prerequisites Ensure you have the following installed on your system: - Git - Rust (latest stable version) - Cargo (comes with Rust) ## Contract Details **Address**: `0x0000000000000000000000000000000000001000` ### Contract Params (Testnet) ```toml TokensPerVote = 30 MaxVotesPerSigner = 1024 MaxQuorums = 10 EpochBlocks = 5760 EncodedSlices = 3072 ``` ## Terminology ### Signer A Signer is an address with sufficient delegations (at least `TokensPerVote` OG) registered in the DASigners module. Each signer should run a DA node to verify DA blob encoding and generate BLS signatures for signed blobs. The BLS curve used is BN254, and the public keys of signers are registered in the contract. **Note**: For accounts with delegations to more than 10 validators, only 10 of these delegations are counted and accumulated. ### Epoch The consecutive blocks in the 0g chain are divided into groups of `EpochBlocks`, and each group is an epoch. ### Quorum In an epoch, there can be up to `MaxQuorums` quorums. Each quorum is a list of signer addresses with size `EncodedSlices`. The i-th signer in the quorum is responsible for validating, signing, and storing the i-th row of the encoded blob data assigned to this quorum. ### Vote Signers can submit their signatures on a registration message to request joining the quorums in the next epoch. At the start of each epoch, the DASigners module calculates the voting power for registered signers based on their delegated token amounts. Each delegated `TokensPerVote` OG counts as one vote, and each signer can have up to `MaxVotesPerSigner` votes. All votes are then randomly ordered and distributed into quorums. ## Interface Find the Solidity interface in the [0g-da-contract repo](https://github.com/0gfoundation/0g-da-contract). ## ABI Find the ABI on the [DASigners precompile page](/developer-hub/building-on-0g/contracts-on-0g/precompiles/precompiles-dasigners#abi). ## Transactions ### registerSigner Register signer's information, including signer address, DA node service socket address, signer BLS public key on G1 and G2 group, and a signature signed by the BLS private key of the following message: ```text Keccak256(signerAddress, chainID, "0G_BN254_Pubkey_Registration") ``` Here `chainID` is left-padded to 32 bytes by zeros. ```solidity function registerSigner( SignerDetail memory _signer, BN254.G1Point memory _signature ) external; ``` ### updateSocket Update signer's socket address. ```solidity function updateSocket(string memory _socket) external; ``` ### registerNextEpoch Register to join the quorums in the next epoch. The signer needs to submit a signature signed by their BLS private key: ```text Keccak256(signerAddress, epoch, chainID) ``` Here `chainID` is left-padded to 32 bytes by zeros and `epoch` is an unsigned 64-bit number in big-endian format. ```solidity function registerNextEpoch(BN254.G1Point memory _signature) external; ``` ## Queries ### epochNumber Get the current epoch number. ```solidity function epochNumber() external view returns (uint); ``` ### quorumCount Get the number of quorums for a given epoch. ```solidity function quorumCount(uint _epoch) external view returns (uint); ``` ### isSigner Check if a given address is a registered signer. ```solidity function isSigner(address _account) external view returns (bool); ``` ### getSigner Get the information of given signers. ```solidity function getSigner(address[] memory _account) external view returns (SignerDetail[] memory); ``` ### getQuorum Get the signer list of a given epoch and quorum id. ```solidity function getQuorum(uint _epoch, uint _quorumId) external view returns (address[] memory); ``` ### getQuorumRow Get the signer of a specific row in a given epoch and quorum id. ```solidity function getQuorumRow(uint _epoch, uint _quorumId, uint32 _rowIndex) external view returns (address); ``` ### registeredEpoch Check if a given address is registered to join the given epoch. ```solidity function registeredEpoch(address _account, uint _epoch) external view returns (bool); ``` ### getAggPkG1 Get the aggregated G1 public key for a given signers set. The signers set is specified by the epoch, quorum id, and a bitmap. The bitmap has `EncodedSlices` bits, and each bit denotes whether the row is chosen or not. ```solidity function getAggPkG1( uint _epoch, uint _quorumId, bytes memory _quorumBitmap ) external view returns (BN254.G1Point memory aggPkG1, uint total, uint hit); ``` --- ## Migrating from geth to reth Source: https://docs.0g.ai/run-a-node/migrate-geth-to-reth.md A 0G node runs two clients in tandem: a **consensus layer (CL)**, `0gchaind`, and an **execution layer (EL)**. The execution layer has historically been **geth**; 0G is now standardizing on **reth** as the recommended execution client. :::info This migration is optional You are **not** required to move to reth to stay on the network — the official release packages continue to ship a geth binary, and a geth node remains a fully valid node. reth is the **recommended** client going forward for better performance, but you can migrate on your own schedule. Do **not** rush a migration to meet an unrelated upgrade deadline; plan it as its own maintenance window. ::: ## Why reth | | geth (`0g-geth`) | reth (`0g-reth`) | | --- | --- | --- | | Language | Go | Rust | | On-disk database | LevelDB | MDBX | | Status on 0G | Supported | **Recommended going forward** | | Sync & storage | Baseline | Faster sync, more efficient storage layout | | Switching cost | — | EL data must be rebuilt (no in-place conversion) | What **does not** change when you migrate: - The **consensus layer** (`0gchaind` / `0gchaind-home`) is untouched — your validator keys, consensus state, and node identity are all preserved. - Your chain data is preserved at the consensus level; only the **execution-layer database** is rebuilt. :::warning Validator keys and double-signing The consensus layer holds your validator key. During any migration you will stop and restart `0gchaind`. **Never run the same `priv_validator_key.json` on two machines at once** — fully stop the old process before starting the new one, or you risk a [double-sign slashing penalty](/run-a-node/validator-node#slashing). ::: This guide covers both **Testnet (Galileo)** and **Mainnet (Aristotle)** and has two parts: 1. **[Fresh reth setup](#fresh-reth-setup)** — for a brand-new node, or one you are rebuilding from scratch. 2. **[Migrating an existing geth node to reth](#migrating-an-existing-geth-node-to-reth)** — to switch an already-running node while preserving consensus state. The node runs: - **Consensus Layer (CL):** `0gchaind` - **Execution Layer (EL):** `reth` --- ## Fresh reth setup ### Hardware requirements | Component | Requirement | | --- | --- | | Memory | 64 GB | | CPU | 8 cores | | Disk | 4 TB NVME SSD | | Bandwidth | 100 MBps Download / Upload | ### Required files All binaries and configuration files are distributed as part of the official release package. After extracting the release, confirm the following files are present in your working directory: | File | Description | | --- | --- | | `bin/0gchaind` | Consensus layer binary | | `bin/reth` | Execution layer binary | | `0g-home/0gchaind-home/config/genesis.json` | CL genesis configuration | | `geth-genesis.json` | EL genesis configuration | | `kzg-trusted-setup.json` | KZG trusted setup for the CL | | `jwt.hex` | JWT secret for CL–EL authentication | ### Download the package (Mainnet) ```bash wget -O aristotle.tar.gz https://github.com/0gfoundation/0gchain-Aristotle/releases/download/v1.0.6/aristotle-v1.0.6.tar.gz tar -xzvf aristotle.tar.gz -C ~ cd Aristotle-v1.0.6 ``` :::note Version Information Latest Aristotle mainnet release: v1.0.6. Check the [releases page](https://github.com/0gfoundation/0gchain-Aristotle/releases) for newer versions. ::: The consensus client requires an **Ethereum mainnet** RPC endpoint to read Symbiotic restaking contract state (e.g. QuickNode, Alchemy, Infura): ```bash export ETH_RPC_URL="https://" ``` ### Initialize the node (Mainnet) :::warning Run once Run this once before the first start. Do not re-run on an already-initialized node — it will overwrite existing state. ::: Set the data directory: ```bash export DATA_DIR=/data/0g-home # or your preferred path mkdir -p $DATA_DIR/log ``` Initialize the consensus layer (`0gchaind`): ```bash ./bin/0gchaind init 0G-mainnet-aristotle-rpc \ --chain-id 0G-mainnet-aristotle \ --chaincfg.chain-spec=mainnet \ --home $DATA_DIR/0gchaind-home ``` | Parameter | Description | | --- | --- | | `0G-mainnet-aristotle-rpc` | Your node's display name (moniker). Customize as needed. | | `--chain-id 0G-mainnet-aristotle` | Chain identifier (mainnet EVM chain ID is `16661`). | | `--chaincfg.chain-spec=mainnet` | Loads mainnet consensus parameters. Required for mainnet validators. | | `--home` | CL data directory. | Copy the genesis file into the CL config directory: ```bash cp -f 0g-home/0gchaind-home/config/genesis.json $DATA_DIR/0gchaind-home/config ``` Initialize the execution layer (`reth`): ```bash ./bin/reth init --chain geth-genesis.json \ --datadir $DATA_DIR/reth-home ``` Verify both data directories were created: ```bash ls $DATA_DIR/0gchaind-home/config/ # Expected: app.toml client.toml config.toml genesis.json jwt.hex node_key.json ls $DATA_DIR/reth-home/ # Expected: db/ and other reth state directories ``` ### Start the node (Mainnet) **Start reth first, wait for the engine API to be ready, then start `0gchaind`.** ```bash export DATA_DIR=/data/0g-home export ETH_RPC_URL="https://" export MY_NODE_IP="" # e.g. 1.2.3.4 ``` Start the execution layer (reth): ```bash nohup ./bin/reth node \ --chain geth-genesis.json \ --http \ --http.addr 0.0.0.0 \ --http.api eth,net,admin \ --authrpc.addr 0.0.0.0 \ --authrpc.jwtsecret jwt.hex \ --datadir $DATA_DIR/reth-home \ --ipcpath $DATA_DIR/reth-home/eth-engine.ipc \ --engine.persistence-threshold 0 \ --engine.memory-block-buffer-target 0 \ --bootnodes="enode://2bf74c837a98c94ad0fa8f5c58a428237d2040f9269fe622c3dbe4fef68141c28e2097d7af6ebaa041194257543dc112514238361a6498f9a38f70fd56493f96@8.221.140.134:30303" \ --nat extip:$MY_NODE_IP \ >> $DATA_DIR/log/reth.log 2>&1 & ``` Confirm the engine API is listening before starting the CL: ```bash ss -tlnp | grep 8551 ``` Start the consensus layer (`0gchaind`): ```bash nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-get-logs-block-range 1 \ --chaincfg.restaking.symbiotic-rpc-dial-url $ETH_RPC_URL \ --home $DATA_DIR/0gchaind-home \ --p2p.external_address $MY_NODE_IP:26656 \ >> $DATA_DIR/log/0gchaind.log 2>&1 & ``` ### Download the package (Testnet) ```bash wget -O galileo.tar.gz https://github.com/0gfoundation/0gchain-NG/releases/latest/download/Galileo-latest.tar.gz tar -xzvf galileo.tar.gz -C ~ cd Galileo- ``` :::note Version Information Check the [Galileo releases page](https://github.com/0gfoundation/0gchain-NG/releases) for the latest version tag, and confirm the package contains `bin/reth`. ::: The consensus client requires an Ethereum **HoleSky testnet** RPC endpoint to read Symbiotic restaking contract state (e.g. QuickNode, Alchemy, Infura): ```bash export ETH_RPC_URL="https://" ``` ### Initialize the node (Testnet) :::warning Run once Run this once before the first start. Do not re-run on an already-initialized node — it will overwrite existing state. ::: Set the data directory: ```bash export DATA_DIR=/data/0g-home # or your preferred path mkdir -p $DATA_DIR/log ``` Initialize the consensus layer (`0gchaind`): ```bash ./bin/0gchaind init 0G-testnet-galileo-rpc \ --chain-id 0G-testnet-galileo \ --chaincfg.chain-spec=testnet \ --home $DATA_DIR/0gchaind-home ``` Copy the genesis file into the CL config directory: ```bash cp -f 0g-home/0gchaind-home/config/genesis.json $DATA_DIR/0gchaind-home/config ``` Initialize the execution layer (`reth`): ```bash ./bin/reth init --chain geth-genesis.json \ --datadir $DATA_DIR/reth-home ``` ### Start the node (Testnet) ```bash export DATA_DIR=/data/0g-home export ETH_RPC_URL="https://" export MY_NODE_IP="" # e.g. 1.2.3.4 ``` Start the consensus layer (`0gchaind`): ```bash nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-get-logs-block-range 1000 \ --chaincfg.restaking.symbiotic-rpc-dial-url $ETH_RPC_URL \ --home $DATA_DIR/0gchaind-home \ --p2p.external_address $MY_NODE_IP:26656 \ >> $DATA_DIR/log/0gchaind.log 2>&1 & ``` Wait until the CL log shows it initializing or connecting to peers, then start the execution layer (reth): ```bash nohup ./bin/reth node \ --chain geth-genesis.json \ --http \ --http.addr 0.0.0.0 \ --http.api eth,net,admin \ --authrpc.addr 0.0.0.0 \ --authrpc.jwtsecret jwt.hex \ --datadir $DATA_DIR/reth-home \ --ipcpath $DATA_DIR/reth-home/eth-engine.ipc \ --engine.persistence-threshold 0 \ --engine.memory-block-buffer-target 0 \ --bootnodes="enode://4f70c6c95329427be4af2a233c9c2305896d37c21bca8c21e7efc36634a862bd5b96b0c4a8a9bb5787b53eb01472fe895aad170d0923f6ea56ebc5f94825c4f7@34.105.23.36:30303" \ --nat extip:$MY_NODE_IP \ >> $DATA_DIR/log/reth.log 2>&1 & ``` ### Key startup parameters | Parameter | Description | | --- | --- | | `--chain geth-genesis.json` | EL genesis file (must match init). | | `--http` / `--http.addr` / `--http.api` | Enables JSON-RPC over HTTP, exposed on all interfaces. | | `--authrpc.addr` / `--authrpc.jwtsecret` | Engine API (CL–EL communication) address and JWT secret. Must match the `jwt.hex` used by the CL. | | `--datadir` | EL data directory (must match init). | | `--ipcpath` | IPC socket path for local engine API access. | | `--engine.persistence-threshold 0` | Persist all blocks immediately. | | `--engine.memory-block-buffer-target 0` | Minimize in-memory block buffering. | | `--bootnodes` | Official network bootnode. Do not modify. | | `--nat extip:$MY_NODE_IP` | Your node's public IP for NAT traversal. Replace with your own IP. | ### Verify the node ```bash # CL logs — look for "Committed state" or peer connection messages tail -f $DATA_DIR/log/0gchaind.log # EL logs — look for "Starting consensus engine" or syncing messages tail -f $DATA_DIR/log/reth.log # Sync status — fully synced when "catching_up" is false curl http://localhost:26657/status | jq '.result.sync_info' ``` --- ## Migrating an existing geth node to reth This section applies when a node is already running with `0gchaind + geth` and you want to switch the EL to reth. ### Background geth and reth use incompatible database formats (LevelDB vs MDBX). **There is no in-place migration path** — the EL data directory must be rebuilt from scratch. The approach is to export geth's chain data as an RLP file and import it into reth. | Component | Impact | | --- | --- | | CL (`0gchaind-home`) | ✅ No change, data is preserved | | EL (`geth-home`) | ❌ Replaced by `reth-home` | | Downtime | Node will miss blocks during migration | ### Known limitations Before proceeding, be aware of the following: - **geth and reth P2P incompatibility:** reth cannot establish peer connections with geth nodes. `connected_peers=0` is expected until a reth-compatible peer is available on the network. - **`reth import` does not support resume:** if the import is interrupted, it cannot resume. It will fail with `block number X does not match parent block number Y`. Use the trimming script (Step 6) to re-export from the correct height. - **State root mismatches:** reth may reject certain blocks from the geth export with `mismatched block state root`. This is a compatibility issue between 0G's geth fork and reth fork. If this occurs, **report the block number and state root values to the 0G development team** — do not attempt to skip the block manually. - **Do not start `0gchaind` until reth has fully synced.** Starting the CL while reth is still syncing will cause a `-38002 Invalid forkchoice state` panic. ### Step 1: Back up existing data ```bash BACKUP_DIR="$DATA_DIR/backup-$(date +%Y%m%d-%H%M%S)" mkdir -p $BACKUP_DIR # CL data (small, required for rollback) cp -r $DATA_DIR/0gchaind-home $BACKUP_DIR/0gchaind-home # geth EL data (large, skip if disk space is tight — # but without this backup you cannot roll back to geth) cp -r $DATA_DIR/geth-home $BACKUP_DIR/geth-home ``` ### Step 2: Get the current chain head, then stop the node **Read the current chain head from geth logs while geth is still running:** ```bash grep -i "number=" $DATA_DIR/log/geth.log | tail -5 ``` Look for a line like `number=39048765` — that is the current head. Note it down for Step 3. Then stop CL first, then EL: ```bash pkill -f 0gchaind while pgrep -f 0gchaind > /dev/null; do echo "Waiting for 0gchaind..."; sleep 3; done pkill -f geth while pgrep -f geth > /dev/null; do echo "Waiting for geth..."; sleep 3; done pgrep -f 0gchaind || echo "CL stopped" pgrep -f geth || echo "EL stopped" ``` ### Step 3: Export geth chain data Export the full chain from block 1 to the current chain head. Both the `` and `` block numbers are required by geth export (replace `` with the value from Step 2): ```bash ./bin/geth export \ --datadir $DATA_DIR/geth-home \ /data/0g-home/chain-export.rlp \ 1 ``` :::note This takes a long time depending on chain height and disk speed. Run it in a `screen` or `tmux` session. ::: ### Step 4: Clear the geth data directory ```bash rm -rf $DATA_DIR/geth-home ``` :::warning Destructive step Only run this after confirming the Step 1 backup is complete. ::: ### Step 5: Initialize reth Confirm the new release package contains `./bin/reth`, then initialize: ```bash ./bin/reth init --chain geth-genesis.json \ --datadir $DATA_DIR/reth-home ``` ### Step 6: Trim the RLP export (skip the genesis block) reth cannot import block 0 (genesis) from the RLP file — it conflicts with the genesis already written during `reth init`. Use the following script to strip block 0 from the export file. The same script can trim to any arbitrary start height, which is needed if the import is interrupted and must resume (see Step 7). Save as `trim_export.py`: ```python import sys input_file = "/data/0g-home/chain-export.rlp" output_file = "/data/0g-home/chain-export-from-{start}.rlp" start_block = int(sys.argv[1]) if len(sys.argv) > 1 else 1 output_file = output_file.format(start=start_block) print(f"Trimming blocks before {start_block}, output: {output_file}") def read_rlp_length(f): first = f.read(1) if not first: return None, 0 b = first[0] if b < 0xc0: return None, 0 elif b <= 0xf7: return first, b - 0xc0 else: len_bytes_count = b - 0xf7 len_bytes = f.read(len_bytes_count) return first + len_bytes, int.from_bytes(len_bytes, 'big') def get_block_number(block_data): offset = 0 b = block_data[offset] offset += 1 if b <= 0xf7 else 1 + (b - 0xf7) b = block_data[offset] offset += 1 if b <= 0xf7 else 1 + (b - 0xf7) for _ in range(8): b = block_data[offset] if b <= 0x80: offset += 1 elif b <= 0xb7: offset += 1 + (b - 0x80) elif b <= 0xbf: n = b - 0xb7 offset += 1 + n + int.from_bytes(block_data[offset+1:offset+1+n], 'big') elif b <= 0xf7: offset += 1 + (b - 0xc0) else: n = b - 0xf7 offset += 1 + n + int.from_bytes(block_data[offset+1:offset+1+n], 'big') b = block_data[offset] if b == 0x80: return 0 if b < 0x80: return b length = b - 0x80 return int.from_bytes(block_data[offset+1:offset+1+length], 'big') block_count = 0 skipped = 0 with open(input_file, "rb") as fin, open(output_file, "wb") as fout: while True: header_bytes, length = read_rlp_length(fin) if header_bytes is None: break block_body = fin.read(length) if len(block_body) < length: break full_block = header_bytes + block_body try: block_number = get_block_number(full_block) except Exception as e: print(f"Warning: could not parse block at index {block_count + skipped}, writing anyway: {e}") fout.write(full_block) block_count += 1 continue if block_number < start_block: skipped += 1 if skipped % 100000 == 0: print(f"Skipped {skipped} blocks (current: {block_number})...") else: fout.write(full_block) block_count += 1 if block_count % 100000 == 0: print(f"Written {block_count} blocks (current: {block_number})...") print(f"Done. Skipped {skipped}, wrote {block_count} blocks to {output_file}") ``` Run (skip genesis only): ```bash python3 trim_export.py 1 ``` Run (resume from a specific height, e.g. after an interrupted import): ```bash python3 trim_export.py ``` :::note The script processes the file as a stream and uses minimal memory. The output filename includes the start block, e.g. `chain-export-from-1.rlp`. ::: ### Step 7: Import into reth Run in the background: ```bash nohup ./bin/reth import \ --chain geth-genesis.json \ --datadir $DATA_DIR/reth-home \ /data/0g-home/chain-export-from-1.rlp \ >> $DATA_DIR/log/reth-import.log 2>&1 & ``` Monitor progress: ```bash tail -f $DATA_DIR/log/reth-import.log ``` **If the import fails mid-way** with `block number X does not match parent block number Y`, the database has partially written data up to height Y. Re-trim the export from Y+1 and re-run: ```bash # Check what height reth rolled back to grep "latest_block" $DATA_DIR/log/reth-import.log | tail -3 # Re-trim from that height python3 trim_export.py # Re-run import with the new trimmed file nohup ./bin/reth import \ --chain geth-genesis.json \ --datadir $DATA_DIR/reth-home \ /data/0g-home/chain-export-from-.rlp \ >> $DATA_DIR/log/reth-import.log 2>&1 & ``` **If the import fails with `mismatched block state root`,** reth's EVM execution produced a different state root than geth recorded — a code-level incompatibility in 0G's fork. Record the failing block number and state root values from the log and report to the 0G development team. Do not attempt to skip the block manually. ### Step 8: Verify the import is complete Once the import finishes, confirm reth's block height matches the chain head **before** starting `0gchaind`: ```bash # Check reth height curl -s -X POST http://localhost:8545 \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ | jq -r '.result' | xargs printf "%d\n" # Check current chain head (testnet endpoint shown; use your network's public RPC) curl -s -X POST https://evmrpc-testnet.0g.ai \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ | jq -r '.result' | xargs printf "%d\n" ``` The two values should be equal or within a few blocks. If reth is still behind, it will catch up via P2P after `0gchaind` is started. :::danger Wait for reth to sync Do **not** proceed until reth height is at or near chain head. Starting `0gchaind` while reth is still syncing will cause a `-38002 Invalid forkchoice state` panic. ::: ### Step 9: Start reth, then 0gchaind Start reth using the start command from the [Fresh reth setup](#start-the-node-mainnet) section for your network, confirm the engine API is listening (`ss -tlnp | grep 8551`), then start `0gchaind`. ```bash tail -f $DATA_DIR/log/0gchaind.log # Expected: "Committed state" messages, no "-38002" errors ``` ### Rollback to geth (if migration fails) If the migration fails and you need to restore geth: ```bash # Stop all processes pkill -f 0gchaind pkill -f reth # Restore geth data from backup rm -rf $DATA_DIR/geth-home cp -r $BACKUP_DIR/geth-home $DATA_DIR/geth-home # Start geth and 0gchaind using the previous startup commands ``` --- ## Troubleshooting **CL fails to start with "missing priv_validator_state.json"** — create an empty state file: ```bash echo '{}' > $DATA_DIR/0gchaind-home/data/priv_validator_state.json ``` **EL and CL not communicating (engine API errors)** — confirm `jwt.hex` in the working directory is the same file used by both `--chaincfg.engine.jwt-secret-path` and `--authrpc.jwtsecret`. They must be identical. **No peers connecting** — ensure port `26656` (CL P2P) and port `30303` (EL P2P) are open on your firewall, and that `--p2p.external_address` / `--nat extip` reflect your correct public IP. Note that reth cannot peer with geth nodes. **`-38002 Invalid forkchoice state`** — reth is still syncing when `0gchaind` started. Stop `0gchaind`, wait for reth to reach chain head, then restart `0gchaind`. --- ## Reference - [Validator Node guide](/run-a-node/validator-node) - [Aristotle release page](https://github.com/0gfoundation/0gchain-Aristotle/releases) - [Galileo release page](https://github.com/0gfoundation/0gchain-NG/releases) --- ## Running a 0G Node Source: https://docs.0g.ai/run-a-node/overview.md --- Want to become an active participant in the 0G network and earn rewards while you're at it? 👇 Each node type plays a crucial role in maintaining the 0G network's functionality, from transaction validation and data storage to ensuring data availability and retrieval. Here, we'll introduce you to the various types of nodes you can run, each contributing to the network's health and security. ## What Nodes Can I Run? ### Validator Nodes The guardians of the network, validator nodes are responsible for verifying transactions, ensuring consensus, and maintaining the blockchain. They're essential for keeping the 0G blockchain secure and running smoothly. ### Storage Nodes Unlike Validator Nodes that focus on securing the blockchain itself, Storage Nodes focus on managing and serving data. They are the backbone of the network's data storage capabilities, ensuring persistence and availability for long-term data storage (e.g., training datasets, large AI models). By running a storage node, you'll contribute to the decentralized storage of 0G data, making it accessible and resilient. ### Data Availability Services DA Nodes are similar to Storage Nodes but focus on immediacy and short-term accessibility to support real-time operations. This data is typically used by Layer 2 and rollup solutions for data availability and is not typically stored long-term. Think of these nodes as the network's librarians, ensuring that data can be quickly retrieved when needed. ### Archival Nodes Archival Nodes maintain complete historical blockchain data and state, providing comprehensive access to the network's entire history. These nodes are essential for applications requiring historical data analysis, compliance, and serving as reliable backups for the network's complete transaction history. ## Why Run a Node? Running a node isn't just about supporting the network; it's also a way to earn rewards for your contribution. By actively participating in the 0G ecosystem, you'll be eligible to receive rewards that incentivize your efforts. ### Ready to Dive In? We've made it easy to get started. The table below outlines the hardware requirements for each type of node, so you can choose the one that best suits your setup. Once you're ready, head over to the 0G documentation for detailed instructions on how to set up and run your chosen node. | Node Type | Description | Memory | CPU | Disk | Bandwidth | |-----------|-------------|--------|-----|------|-----------| | Validator Node | Validates transactions and maintains network consensus | 64 GB | 8 cores | 1 TB NVME SSD (4 TB on Testnet) | 100 MBps | | Storage Node | Stores data within the 0g network | 16 GB | 4 cores | 500GB / 1T NVME SSD | 500 MBps | | Storage KV | Handles key-value storage operations | 4 GB | 2 cores | Matches KV streams size | - | | DA Node | Performs blob data verification, signing, and storage | 16 GB | 8 cores | 1 TB NVME SSD | 100 MBps | | DA Retriever | Retrieves data availability information | 8 GB | 2 cores | - | 100 MBps | | DA Encoder* | Encodes data for availability purposes | - | - | - | - | | DA Client | Interacts with the Data Availability layer | 8 GB | 2 cores | - | 100 MBps | *Note: For DA Encoder, GPU support is currently tested with NVIDIA 12.04 drivers on the RTX 4090. Other NVIDIA GPUs may require parameter adjustments and have not been tuned yet.* ### Next Steps Ready to set up your node? Check out our detailed guides: - [Validator Node Setup Guide](validator-node.md) - [Storage Node Setup Guide](storage-node.md) - [Data Availability Service Setup Guide](da-node.md) - [Archival Node Setup Guide](archival-node.md) --- ## Storage Node Source: https://docs.0g.ai/run-a-node/storage-node.md --- In the 0G network, storage nodes play a vital role in maintaining the system's decentralized storage layer. They are responsible for storing and serving data, ensuring data availability and reliability across the network. By running a storage node, you actively contribute to the network and earn rewards for your participation. This guide details the process of running a storage node, including hardware specifications and interaction with on-chain contracts. ## Hardware Requirements | Component | Storage Node | Storage KV | |-----------|--------------|------------| | Memory | 32 GB RAM | 32 GB RAM | | CPU | 8 cores | 8 cores | | Disk | 500GB / 1TB SSD | Size matches the KV streams it maintains | | Bandwidth | 100 Mbps (Download / Upload) | - | :::note - For Storage Node: The SSD ensures fast read/write operations, critical for efficient blob storage and retrieval. - For Storage KV: The disk size requirement is flexible and should be adjusted based on the volume of KV streams you intend to maintain. ::: ## Next Steps For detailed instructions on setting up and operating your Storage Node or Storage KV, please refer to our comprehensive setup guides below: ## Prerequisites Before setting up your storage node: - Understand that 0G Storage interacts with on-chain contracts for blob root confirmation and PoRA mining. - Choose your network: [Testnet](../developer-hub/testnet/testnet-overview.md) or [Mainnet](../developer-hub/mainnet/mainnet-overview.md) - Check the respective network overview pages for deployed contract addresses and RPC endpoints. - **For mainnet deployment**: Ensure you have real 0G tokens for transaction fees and mining rewards. ## Install Dependencies Start by installing all the essential tools and libraries required to build the 0G storage node software. ```bash sudo apt-get update sudo apt-get install clang cmake build-essential pkg-config libssl-dev protobuf-compiler ``` ```bash brew install llvm cmake ``` **Install `rustup`**: rustup is the Rust toolchain installer, necessary as the 0G node software is written in Rust. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` **Download the Source Code**: ```bash git clone -b https://github.com/0gfoundation/0g-storage-node.git ``` **Build the Source Code** ```bash cd 0g-storage-node # Build in release mode cargo build --release ``` This compiles the Rust code into an executable binary. The `--release` flag optimizes the build for performance. ## Setup and Configuration Navigate to the run directory and configure your storage node for either testnet or mainnet. :::info Config File References The official configuration files are in the `run/` directory. Currently only `turbo` is available: ```text run/config-testnet-turbo.toml run/config-mainnet-turbo.toml ``` Always use the latest versions from the repository as they contain the most up-to-date network parameters. ::: **Turbo vs Standard** Both `turbo` and `standard` configs are identical in structure and fields. The only difference is pricing; choose the file that matches the pricing tier you want to run. **Where The Full Config Is Explained** The most detailed, up-to-date comments for every field live in `run/config-testnet-turbo.toml` (and the corresponding `run/config-testnet-standard.toml`). Use those files as the authoritative field-by-field explanation. **Key Fields (Same Wording As `run/config-testnet-turbo.toml`)** `network_boot_nodes` Note: List of nodes to bootstrap UDP discovery. Note, `network_enr_address` should be configured as well to enable UDP discovery. `log_contract_address` Note: Flow contract address to sync event logs. `mine_contract_address` Note: Mine contract address for incentive. `reward_contract_address` Note: Reward contract address. `db_max_num_sectors` Note: The max number of chunk entries to store in db. Each entry is 256B, so the db size is roughly limited to `256 * db_max_num_sectors` Bytes. If this limit is reached, the node will update its `shard_position` and store only half data. `chunk_pool_write_window_size` Note: Maximum number of threads to upload segments of a single file simultaneously. `chunk_pool_max_writings` Note: Maximum number of threads to upload segments for all files simultaneously. `auto_sync_enabled` Note: Enable file sync among peers automatically. When enabled, each node will store all files, and sufficient disk space is required. `neighbors_only` Note: Indicates whether to sync file from neighbor nodes only. This is to avoid flooding file announcements in the whole network, which leads to high latency or even timeout to sync files. **CLI Options** CLI flags override values in `config.toml`. - `-c`, `--config `: Sets a custom config file. - `--log-config-file [FILE]`: Sets log configuration file (Default: `log_config`). - `--miner-key [KEY]`: Sets miner private key (Default: None). - `--blockchain-rpc-endpoint [URL]`: Sets blockchain RPC endpoint (Default: `http://127.0.0.1:8545`). - `--db-max-num-chunks [NUM]`: Sets the max number of chunks to store in DB (Default: None). - `--network-enr-address [URL]`: Sets the network ENR address (Default: None). **Configuration Reference** Full configuration keys are defined in `node/src/config/mod.rs` and log sync behavior is implemented in `node/log_entry_sync/src/sync_manager/config.rs`. **Network** - `network_dir`: Directory for node keyfile and network data (Default: `network`). - `network_listen_address`: IP address to listen on (Default: `0.0.0.0`). - `network_enr_address`: Public address advertised in ENR (Default: None). - `network_enr_tcp_port`: TCP port advertised in ENR (Default: `1234`). - `network_enr_udp_port`: UDP port advertised in ENR (Default: `1234`). - `network_libp2p_port`: Libp2p TCP port (Default: `1234`). - `network_discovery_port`: Discovery UDP port (Default: `1234`). - `network_target_peers`: Target number of connected peers (Default: `50`). - `network_boot_nodes`: ENR boot nodes list for discovery (Default: empty list). - `network_libp2p_nodes`: Initial libp2p peers to connect to (Default: empty list). - `network_private`: Enable private mode (Default: `false`). - `network_disable_discovery`: Disable discovery protocol (Default: `false`). - `network_find_chunks_enabled`: Enable find-chunks behavior (Default: `false`). **Discv5** - `discv5_request_timeout_secs`: Timeout per UDP request (Default: `5`). - `discv5_query_peer_timeout_secs`: Timeout to mark a query peer unresponsive (Default: `2`). - `discv5_request_retries`: Retry count for UDP requests (Default: `1`). - `discv5_query_parallelism`: Parallelism per query (Default: `5`). - `discv5_report_discovered_peers`: Emit discovered ENRs during traversal (Default: `false`). - `discv5_disable_packet_filter`: Disable incoming packet filter (Default: `false`). - `discv5_disable_ip_limit`: Disable /24 subnet limit in kbuckets (Default: `false`). - `discv5_disable_enr_network_id`: Disable ENR network ID checks (Default: `false`). **Log Sync** - `blockchain_rpc_endpoint`: RPC endpoint to sync EVM logs (Default: `http://127.0.0.1:8545`). - `log_contract_address`: Flow contract address to sync logs from (Default: empty). - `log_sync_start_block_number`: Block number to start syncing logs (Default: `0`). - `force_log_sync_from_start_block_number`: Force sync from start block even if progress exists (Default: `false`). - `confirmation_block_count`: Blocks required for confirmation to handle reorgs (Default: `3`). - `log_page_size`: Max number of logs per poll (Default: `999`). - `max_cache_data_size`: Max cached data size in bytes (Default: `104857600`). - `cache_tx_seq_ttl`: Cache TTL for tx sequence entries (Default: `500`). - `rate_limit_retries`: Retries after RPC timeouts (Default: `100`). - `timeout_retries`: Retries for rate-limited responses (Default: `100`). - `initial_backoff`: Initial backoff in ms before retry (Default: `500`). - `recover_query_delay`: Delay in ms between paginated getLogs calls (Default: `50`). - `default_finalized_block_count`: Finality lag assumed behind latest block (Default: `100`). - `remove_finalized_block_interval_minutes`: Interval in minutes to prune finalized blocks (Default: `30`). - `watch_loop_wait_time_ms`: Watch loop delay in ms (Default: `500`). - `blockchain_rpc_timeout_secs`: RPC connect/read timeout in seconds (Default: `120`). **Chunk Pool** - `chunk_pool_write_window_size`: Max threads per file upload (Default: `4`). - `chunk_pool_max_cached_chunks_all`: Max cached chunk bytes across all files (Default: `4194304`). - `chunk_pool_max_writings`: Max concurrent file uploads (Default: `16`). - `chunk_pool_expiration_time_secs`: Cached chunk expiration in seconds (Default: `300`). **Database** - `db_dir`: Directory to store data (Default: `db`). - `db_max_num_sectors`: Max number of chunk entries to store (Default: None). - `prune_check_time_s`: Interval to check prune conditions in seconds (Default: `60`). - `prune_batch_size`: Number of entries per prune batch (Default: `16384`). - `prune_batch_wait_time_ms`: Wait between prune batches in ms (Default: `1000`). - `merkle_node_cache_capacity`: Merkle node cache capacity in bytes (Default: `33554432`). **Misc** - `log_config_file`: Log configuration file name (Default: `log_config`). - `log_directory`: Directory for log output (Default: `log`). **Mining** - `mine_contract_address`: Mine contract address (Default: empty). - `miner_id`: Optional miner ID (Default: None). - `miner_key`: Miner private key (Default: None). - `miner_cpu_percentage`: CPU usage percentage for mining (Default: `100`). - `mine_iter_batch_size`: Mining iteration batch size (Default: `100`). - `reward_contract_address`: Reward contract address (Default: empty). - `shard_position`: Shard selector in `/` format (Default: None). - `mine_context_query_seconds`: Interval to query mine context in seconds (Default: `5`). ### Configuration 1. Copy the testnet configuration: ```bash cd run cp config-testnet-turbo.toml config.toml ``` 2. Update the following fields in `config.toml`: ```toml # Contract addresses for testnet log_contract_address = "FLOW_CONTRACT_ADDRESS" mine_contract_address = "MINE_CONTRACT_ADDRESS" # Testnet RPC endpoint blockchain_rpc_endpoint = "https://evmrpc-testnet.0g.ai" # Start sync block number for testnet log_sync_start_block_number = 1 # Reward contract for testnet reward_contract_address = "REWARD_CONTRACT_ADDRESS" # Your private key for mining (64 chars, no '0x' prefix) miner_key = "YOUR_PRIVATE_KEY" ``` 3. Optional: Configure network settings if needed: ```toml # Target number of connected peers (can be increased for better connectivity) network_target_peers = 50 ``` ### Sharding Configuration Sharding allows you to control how much data your storage node stores. This is particularly useful when disk space is limited. #### Understanding Shard Position The `shard_position` parameter determines which portion of the total network data your node stores: ```toml # Format: shard_id/shard_number where shard_number is 2^n # This only applies if there is no stored shard config in db shard_position = "0/2" ``` **Format**: `/` - `shard_id`: Which shard this node stores (0, 1, 2, 3, etc.) - `shard_number`: Total number of shards (must be a power of 2: 2, 4, 8, 16, etc.) **Examples**: - `shard_position = "0/2"` → Store 50% of data (shard 0 of 2 total shards) - `shard_position = "1/2"` → Store 50% of data (shard 1 of 2 total shards) - `shard_position = "0/4"` → Store 25% of data (shard 0 of 4 total shards) - `shard_position = "2/4"` → Store 25% of data (shard 2 of 4 total shards) Each shard stores a **specific range** of the total data. For example, with `0/2` and `1/2`, both store 50% of data but on different, non-overlapping ranges. #### How Sharding Works Consider a scenario with 128 GB total network data and a 100 GB disk: 1. **Initial Setup** (`shard_position = "0/2"`): - Your node stores 64 GB (50% of 128 GB) - Stores a specific, deterministic data range - Fits comfortably on your 100 GB disk 2. **Network Growth** (total data becomes 256 GB): - Your node would be responsible for 128 GB (50% of 256 GB) - This exceeds your 100 GB disk capacity - **Automatic adjustment**: Node automatically splits to `x/4` - Now stores 64 GB (25% of 256 GB) - `shard_id` changes: `0` → `0 or 2`, `1` → `1 or 3` (randomly assigned by the node, you cannot control which) #### Automatic Shard Division When network data exceeds your disk capacity, the node automatically: - Doubles the shard number (2 → 4 → 8 → 16, etc.) - Randomly reassigns to a new shard within the split (you cannot control which) - Maintains storage within disk limits :::warning Important Notes - **Initial setup is deterministic**: When you first configure `shard_position`, the shard_id deterministically maps to a specific data range - This setting only applies on **first startup** if no shard config exists in the database - **Auto-splitting is NOT deterministic**: When the node automatically splits shards due to capacity limits, you cannot control which new shard_id you get - it's randomly assigned - Once shard config is stored in the database, the node manages all future shard adjustments automatically ::: #### Choosing Your Shard Configuration To determine the right shard configuration: 1. **Estimate network data size**: Check current total data on the network 2. **Consider disk capacity**: Leave headroom for growth (e.g., use 70-80% of disk) 3. **Calculate shard number**: `shard_number = total_data / (disk_capacity * 0.75)` 4. **Round up to nearest power of 2**: 2, 4, 8, 16, 32, etc. **Example**: - Network data: 500 GB - Your disk: 200 GB - Safe storage: 150 GB (75% of disk) - Calculation: 500 / 150 ≈ 3.33 → Round up to 4 - Configuration: `shard_position = "0/4"` (stores ~125 GB) ### Running the Node 1. Check configuration options: ```bash ../target/release/zgs_node -h ``` 2. Run the testnet storage service: ```bash cd run ../target/release/zgs_node --config config.toml --miner-key ``` ### Configuration 1. Copy the mainnet configuration: ```bash cd run cp config-mainnet-turbo.toml config.toml ``` 2. Update the following fields in `config.toml`: ```toml # Contract addresses for mainnet log_contract_address = "FLOW_CONTRACT_ADDRESS" mine_contract_address = "MINE_CONTRACT_ADDRESS" reward_contract_address = "REWARD_CONTRACT_ADDRESS" # Mainnet RPC endpoint blockchain_rpc_endpoint = "https://evmrpc.0g.ai" # Start sync block number for mainnet log_sync_start_block_number = 2387557 # Your private key for mining (64 chars, no '0x' prefix) miner_key = "YOUR_PRIVATE_KEY" ``` 3. The mainnet configuration includes predefined boot nodes for network connectivity: ```toml network_boot_nodes = ["/ip4/34.66.131.173/udp/1234/p2p/16Uiu2HAmG81UgZ1JJLx9T2HqELgJNP36ChHzYkCdA9HdxvAbb5jQ","/ip4/34.60.163.4/udp/1234/p2p/16Uiu2HAmL3DoA7e7mbxs7CkeCPtNrAcfJFFtLpJDr2HWuR6QwJ8k","/ip4/34.169.236.186/udp/1234/p2p/16Uiu2HAm489RdhEgZUFmNTR4jdLEE4HjrvwaPCkEpSYSgvqi1CbR","/ip4/34.71.110.60/udp/1234/p2p/16Uiu2HAmBfGfbLNRegcqihiuXhgSXWNpgiGm6EwW2SYexfPUNUHQ"] ``` ### Sharding Configuration Sharding allows you to control how much data your storage node stores. This is particularly useful when disk space is limited. #### Understanding Shard Position The `shard_position` parameter determines which portion of the total network data your node stores: ```toml # Format: shard_id/shard_number where shard_number is 2^n # This only applies if there is no stored shard config in db shard_position = "0/2" ``` **Format**: `/` - `shard_id`: Which shard this node stores (0, 1, 2, 3, etc.) - `shard_number`: Total number of shards (must be a power of 2: 2, 4, 8, 16, etc.) **Examples**: - `shard_position = "0/2"` → Store 50% of data (shard 0 of 2 total shards) - `shard_position = "1/2"` → Store 50% of data (shard 1 of 2 total shards) - `shard_position = "0/4"` → Store 25% of data (shard 0 of 4 total shards) - `shard_position = "2/4"` → Store 25% of data (shard 2 of 4 total shards) Each shard stores a **specific range** of the total data. For example, with `0/2` and `1/2`, both store 50% of data but on different, non-overlapping ranges. #### How Sharding Works Consider a scenario with 128 GB total network data and a 100 GB disk: 1. **Initial Setup** (`shard_position = "0/2"`): - Your node stores 64 GB (50% of 128 GB) - Stores a specific, deterministic data range - Fits comfortably on your 100 GB disk 2. **Network Growth** (total data becomes 256 GB): - Your node would be responsible for 128 GB (50% of 256 GB) - This exceeds your 100 GB disk capacity - **Automatic adjustment**: Node automatically splits to `x/4` - Now stores 64 GB (25% of 256 GB) - `shard_id` changes: `0` → `0 or 2`, `1` → `1 or 3` (randomly assigned by the node, you cannot control which) #### Automatic Shard Division When network data exceeds your disk capacity, the node automatically: - Doubles the shard number (2 → 4 → 8 → 16, etc.) - Randomly reassigns to a new shard within the split (you cannot control which) - Maintains storage within disk limits :::warning Important Notes - **Initial setup is deterministic**: When you first configure `shard_position`, the shard_id deterministically maps to a specific data range - This setting only applies on **first startup** if no shard config exists in the database - **Auto-splitting is NOT deterministic**: When the node automatically splits shards due to capacity limits, you cannot control which new shard_id you get - it's randomly assigned - Once shard config is stored in the database, the node manages all future shard adjustments automatically ::: #### Choosing Your Shard Configuration To determine the right shard configuration: 1. **Estimate network data size**: Check current total data on the network 2. **Consider disk capacity**: Leave headroom for growth (e.g., use 70-80% of disk) 3. **Calculate shard number**: `shard_number = total_data / (disk_capacity * 0.75)` 4. **Round up to nearest power of 2**: 2, 4, 8, 16, 32, etc. **Example**: - Network data: 500 GB - Your disk: 200 GB - Safe storage: 150 GB (75% of disk) - Calculation: 500 / 150 ≈ 3.33 → Round up to 4 - Configuration: `shard_position = "0/4"` (stores ~125 GB) ### Running the Node 1. Check configuration options: ```bash ../target/release/zgs_node -h ``` 2. Run the mainnet storage service: ```bash cd run ../target/release/zgs_node --config config.toml --miner-key ``` **Important Mainnet Notes**: - Ensure your miner key has sufficient 0G tokens for transaction fees - Mainnet nodes should have stable internet connectivity and sufficient bandwidth - Monitor your node's performance and logs regularly ## Snapshot Make sure to only include `flow_db` and delete `data_db` under `db` folder when you use a snapshot from a 3rd party ! > Using others' `data_db` will make the node mine for others! **Additional Notes** * **Security:** Keep your private key (`miner_key`) safe and secure. Anyone with access to it can control your node and potentially claim your mining rewards. * **Network Connectivity:** Ensure your node has a stable internet connection and that the necessary ports are open for communication with other nodes. * **Monitoring:** Monitor your node's logs and resource usage to ensure it's running smoothly. * **Updates:** Stay informed about updates to the 0G storage node software and follow the project's documentation for any changes in the setup process. **Remember:** Running a storage node is a valuable contribution to the 0G network. You'll be helping to maintain its decentralization and robustness while earning rewards for your efforts. ## Overview 0G Storage KV is a key-value store built on top of the 0G Storage system. This guide provides detailed steps to deploy and run a 0G Storage KV node. ## Prerequisites Before setting up your 0G Storage KV node: - Understand that 0G KV interacts with on-chain contracts and storage nodes to simulate KV data streams. - For official deployed contract addresses, visit the [testnet information page](../developer-hub/testnet/testnet-overview.md). ## Install Dependencies Follow the same steps to install dependencies and Rust as in the storage node setup: ```bash sudo apt-get update sudo apt-get install clang cmake build-essential pkg-config libssl-dev protobuf-compiler ``` ```bash brew install llvm cmake ``` **Install `rustup`**: rustup is the Rust toolchain installer, necessary as the 0G node software is written in Rust. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` #### 1. Download the Source Code ```bash git clone -b https://github.com/0gfoundation/0g-storage-kv.git ``` #### 2. Build the Source Code ```bash cd 0g-storage-kv # Build in release mode cargo build --release ``` ## Configuration 1. Copy the example configuration file and update it: ```bash cp config_example.toml config.toml nano config.toml ``` 2. Update the following fields in `config.toml`: ```toml ####################################################################### ### Key-Value Stream Options ### ####################################################################### # Streams to monitor. stream_ids = ["000000000000000000000000000000000000000000000000000000000000f2bd", "000000000000000000000000000000000000000000000000000000000000f009", "0000000000000000000000000000000000000000000000000000000000016879", "0000000000000000000000000000000000000000000000000000000000002e3d"] ####################################################################### ### DB Config Options ### ####################################################################### # Directory to store data. db_dir = "db" # Directory to store KV Metadata. kv_db_dir = "kv.DB" ####################################################################### ### Log Sync Config Options ### ####################################################################### blockchain_rpc_endpoint = "BLOCKCHAIN_RPC_ENDPOINT" #rpc endpoint, see testnet information log_contract_address = "LOG_CONTRACT_ADDRESS" #flow contract address, see testnet information # log_sync_start_block_number should be earlier than the block number of the first transaction that writes to the stream being monitored. log_sync_start_block_number = 0 ####################################################################### ### RPC Config Options ### ####################################################################### # Whether to provide RPC service. rpc_enabled = true # HTTP server address to bind for public RPC. rpc_listen_address = "0.0.0.0:6789" # Zerog storage nodes to download data from. zgs_node_urls = "http://127.0.0.1:5678,http://127.0.0.1:5679" ####################################################################### ### Misc Config Options ### ####################################################################### log_config_file = "log_config" ``` ## Running the Storage KV Node 1. Navigate to the `run` directory: ```bash cd run ``` 2. Run the KV service: ```bash ../target/release/zgs_kv --config config.toml ``` For long-running sessions, consider using `tmux` or `screen` to run the node in the background. ## Monitoring and Maintenance 1. Check logs: The node outputs logs based on the `log_config` file specified in your configuration. 2. Updating the node: To update to the latest version, pull the latest changes from the repository and rebuild: ```bash git pull cargo build --release ``` ## Troubleshooting If you encounter issues: 1. Check the logs for any error messages. 2. Ensure your node meets the hardware requirements. 3. Verify that your `config.toml` file is correctly formatted and contains valid settings. 4. Check your internet connection and firewall settings. 5. Ensure the specified blockchain RPC endpoint and contract addresses are correct and accessible. ## Getting Help If you need assistance: 1. Check the [GitHub Issues](https://github.com/0gfoundation/0g-storage-kv/issues) for known problems and solutions. 2. Join the 0G community channels (Discord, Telegram, etc.) for community support. 3. For critical issues, consider reaching out to the 0G team directly. ## Conclusion Running a 0G Storage KV node is an important part of the 0G ecosystem, providing key-value storage capabilities. By following this guide, you should be able to set up and operate your node successfully. Remember to keep your node updated and monitor its performance regularly to ensure optimal operation. --- ## Validator Node Source: https://docs.0g.ai/run-a-node/validator-node.md --- Running a Validator node means providing validator services for the network, processing transactions and maintaining consensus. :::info **What You'll Need** - Linux/macOS system with adequate hardware - Stable internet connection - Ethereum RPC endpoint (mainnet for Aristotle, HoleSky testnet for Galileo) ::: ## Hardware Requirements | Component | Mainnet (Aristotle) | Testnet (Galileo) | |------------|---------|----------| | Memory | 64 GB | 64 GB | | CPU | 8 cores | 8 cores | | Disk | 1 TB NVME SSD | 4 TB NVME SSD | | Bandwidth | 100 MBps for Download / Upload | 100 MBps for Download / Upload | ## Restaking RPC Configuration - **Validator Nodes**: When running your consensus client, add the following flags to enable restaking and configure the Symbiotic RPC: ```bash --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \ --chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} ``` - **ETH_RPC_URL**: The RPC endpoint for the Symbiotic network. - **Mainnet (Aristotle)**: Use an Ethereum Mainnet RPC endpoint (e.g., `https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY`) - **Testnet (Galileo)**: Use an Ethereum HoleSky RPC endpoint - **BLOCK_NUM**: The maximum block number range per call when syncing restaking events. Default is 1. Adjust based on your RPC provider limits. - **Non-Validator Nodes**: No restaking-related configuration is required; you can keep your current startup parameters unchanged. This enables staking in Symbiotic contracts on Ethereum (mainnet: Ethereum, testnet: HoleSky) to participate in 0G Chain consensus. Validators must be able to read the Ethereum contract state to generate and verify new blocks. You can run your own node or use a third-party RPC provider such as QuickNode or Infura for `${ETH_RPC_URL}`. :::tip Non-Validator Nodes Restaking configuration is NOT required for non-validator nodes. Do not add the `--chaincfg.restaking.*` flags when running non-validator nodes. ::: :::tip Execution client: reth is recommended The setup guides below use **geth** as the execution client. **reth** is the recommended execution client going forward — it offers faster sync and a more efficient on-disk database. If you are setting up a new node or want to switch an existing one, see **[Migrating from geth to reth](/run-a-node/migrate-geth-to-reth)**. ::: --- ## Mainnet (Aristotle) Setup Guide ### 1. Download Package Download the latest Aristotle mainnet package: ```bash wget -O aristotle.tar.gz https://github.com/0gfoundation/0gchain-Aristotle/releases/download/v1.0.6/aristotle-v1.0.6.tar.gz ``` :::note Version Information Latest Aristotle mainnet release: v1.0.6. Check [releases page](https://github.com/0gfoundation/0gchain-Aristotle/releases) for newer versions. ::: ### 2. Extract Package Extract the Aristotle node package to your home directory: ```bash tar -xzvf aristotle-v1.0.6.tar.gz -C ~ ``` ### 3. Create Data Directory and Copy Configuration Create your data directory and copy the default configuration: ```bash cd Aristotle-v1.0.6 cp -r 0g-home {your data path} sudo chmod 777 ./bin/geth sudo chmod 777 ./bin/0gchaind ``` ### 4. Initialize Geth Initialize the Geth execution client with the genesis configuration: ```bash ./bin/geth init --datadir {your data path}/0g-home/geth-home ./geth-genesis.json ``` **Expected output:** "Successfully wrote genesis state" ### 5. Initialize 0gchaind for Mainnet Create a temporary initialization with the mainnet chain specification: ```bash ./bin/0gchaind init {node name} --home {your data path}/tmp --chaincfg.chain-spec mainnet ``` ⚠️ **Important:** The `--chaincfg.chain-spec mainnet` flag is REQUIRED for validators ### 6. Copy Node Keys and Validator Keys Copy all necessary keys to the permanent directory: ```bash cp {your data path}/tmp/data/priv_validator_state.json {your data path}/0g-home/0gchaind-home/data/ cp {your data path}/tmp/config/node_key.json {your data path}/0g-home/0gchaind-home/config/ cp {your data path}/tmp/config/priv_validator_key.json {your data path}/0g-home/0gchaind-home/config/ ``` ### 7. Generate JWT Authentication Token Generate a JWT token with mainnet specification for secure communication: ```bash ./bin/0gchaind jwt generate --home {your data path}/0g-home/0gchaind-home --chaincfg.chain-spec mainnet cp -f {your data path}/0g-home/0gchaind-home/config/jwt.hex ./ ``` ### 8. Configure Node Name Update the node moniker in the configuration file: ```bash sed -i 's/moniker = "0G-mainnet-aristotle-node"/moniker = "{your node name}"/' {your data path}/0g-home/0gchaind-home/config/config.toml ``` ### 9. Verify Configuration Files Ensure all required configuration files are present: ```bash ls -la {your data path}/0g-home/0gchaind-home/config/ ``` **Should display:** - `app.toml` - `client.toml` - `config.toml` - `genesis.json` - `jwt.hex` - `node_key.json` - `priv_validator_key.json` ### 10. Set Environment Variables Configure required environment variables for Symbiotic restaking: ```bash # Set your Ethereum RPC endpoint (mainnet) export ETH_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" # Set block range for syncing (adjust based on your RPC limits) export BLOCK_NUM=1 ``` ### 11. Start 0gchaind Launch the 0gchaind consensus client with validator-specific parameters: ```bash cd Aristotle-v1.0.6 nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \ --chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \ --home {your data path}/0g-home/0gchaind-home \ --p2p.external_address {your node ip}:26656 > {your data path}/0g-home/log/0gchaind.log 2>&1 & ``` **Validator-Specific Parameters:** - `--chaincfg.restaking.enabled`: Enables restaking functionality - `--chaincfg.restaking.symbiotic-rpc-dial-url`: Ethereum RPC for Symbiotic protocol - `--chaincfg.restaking.symbiotic-get-logs-block-range`: Block range per sync call ### 12. Start Geth Launch the Geth execution client: ```bash cd Aristotle-v1.0.6 nohup ./bin/geth \ --config geth-config.toml \ --nat extip:{your node ip} \ --datadir {your data path}/0g-home/geth-home \ --networkid 16661 > {your data path}/0g-home/log/geth.log 2>&1 & ``` ### 13. Verify Node Status Check that both services are running correctly: ```bash # Check 0gchaind logs tail -f {your data path}/0g-home/log/0gchaind.log # Check geth logs tail -f {your data path}/0g-home/log/geth.log ``` ## Testnet (Galileo) Setup Guide ### 1. Download Package Download the latest Galileo testnet package: ```bash wget -O galileo.tar.gz https://github.com/0gfoundation/0gchain-NG/releases/download/v3.0.4/Galileo-v3.0.4.tar.gz ``` :::note Version Information Latest Galileo testnet release: v3.0.4. Check [releases page](https://github.com/0gfoundation/0gchain-NG/releases) for newer versions. ::: ### 2. Extract Package Extract the package to your home directory: ```bash tar -xzvf Galileo-v3.0.4.tar.gz -C ~ ``` ### 3. Create Data Directory and Copy Configuration Copy the configuration files and set proper permissions: ```bash cd Galileo-v3.0.4 cp -r 0g-home {your data path} sudo chmod 777 ./bin/geth sudo chmod 777 ./bin/0gchaind ``` ### 4. Initialize Geth Initialize the Geth execution client with the genesis file: ```bash ./bin/geth init --datadir {your data path}/0g-home/geth-home ./geth-genesis.json ``` **Expected output:** "Successfully wrote genesis state" ### 5. Initialize 0gchaind for Testnet Create a temporary directory for initial configuration with testnet chain specification: ```bash ./bin/0gchaind init {node name} --home {your data path}/tmp --chaincfg.chain-spec testnet ``` ⚠️ **Important:** The `--chaincfg.chain-spec testnet` flag is REQUIRED for testnet validators ### 6. Generate JWT Authentication Token Generate a JWT token with testnet specification for secure communication: ```bash ./bin/0gchaind jwt generate --home {your data path}/0g-home/0gchaind-home --chaincfg.chain-spec testnet cp -f {your data path}/0g-home/0gchaind-home/config/jwt.hex ./ ``` ### 7. Copy Node Files Move the generated keys to the proper location: ```bash cp {your data path}/tmp/data/priv_validator_state.json {your data path}/0g-home/0gchaind-home/data/ cp {your data path}/tmp/config/node_key.json {your data path}/0g-home/0gchaind-home/config/ cp {your data path}/tmp/config/priv_validator_key.json {your data path}/0g-home/0gchaind-home/config/ ``` > Note: The temporary directory can be deleted after this step. ### 8. Set Environment Variables Configure required environment variables for Symbiotic restaking: ```bash # Set your Ethereum HoleSky RPC endpoint (testnet) export ETH_RPC_URL="https://holesky-rpc.g.alchemy.com/v2/YOUR_API_KEY" # Set block range for syncing (adjust based on your RPC limits) export BLOCK_NUM=1 ``` ### 9. Start 0gchaind Launch the 0gchaind consensus client with testnet parameters: ```bash cd ~/Galileo-v3.0.4 nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.chain-spec testnet \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \ --chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \ --home {your data path}/0g-home/0gchaind-home \ --p2p.external_address {your node ip}:26656 > {your data path}/0g-home/log/0gchaind.log 2>&1 & ``` ### 10. Start Geth Launch the Geth execution client: ```bash cd ~/Galileo-v3.0.4 nohup ./bin/geth \ --config geth-config.toml \ --nat extip:{your node ip} \ --datadir {your data path}/0g-home/geth-home \ --networkid 16602 > {your data path}/0g-home/log/geth.log 2>&1 & ``` ### 11. Verify Setup Check the logs to confirm your node is running properly: ```bash # Check 0gchaind logs tail -f {your data path}/0g-home/log/0gchaind.log # Check geth logs tail -f {your data path}/0g-home/log/geth.log ``` :::success **Success Indicators** - 0gchaind should show "Committed state" messages - No error messages in either log - Validator is participating in consensus ::: --- ## Validator Operations ### Slashing 0G Chain enforces **double-sign (equivocation) slashing** as a standing consensus rule. If a validator signs two conflicting votes at the same block height, the consensus layer applies a balance penalty. - **Penalty:** 2% of the validator's effective balance (minimum 1 gwei). - **Most common cause:** running the **same validator key on more than one node** at the same time (e.g. a forgotten old node, or a failover that did not fully stop the primary). :::danger Avoid double-signing Never run the same `priv_validator_key.json` on two nodes simultaneously. When migrating, upgrading, or failing over, **fully stop the old node** (confirm the process is gone) before starting the new one. There is no "standby" mode that is safe to run with the same key. ::: ### Initialize Your Validator Once your validator node is running and fully synced (`catching_up: false`), you need to initialize your validator on the blockchain to start validating transactions. **Next Step:** Follow the **[Validator Initialization Guide](../developer-hub/building-on-0g/contracts-on-0g/staking-interfaces#validator-initialization)** to: 1. Generate validator signature 2. Prepare validator description and settings 3. Execute the initialization transaction 4. Verify your validator activation (typically 30-60 minutes) --- ### Monitor Consensus Participation ```bash # Check if your validator is in the active set curl http://localhost:26657/validators | jq ``` ### Check Sync Status ```bash # Should show "catching_up": false when fully synced curl http://localhost:26657/status | jq '.result.sync_info' ``` ### Key Management ⚠️ **Critical Security Notice:** - **Backup your validator keys immediately**: `priv_validator_key.json` and `node_key.json` - **Never share your private validator key** with anyone - Store backups in multiple secure locations - Test recovery process in a non-production environment first
Backup & Recovery These files are essential for validator recovery and must be backed up securely: ```bash # Essential validator keys /{your data path}/0g-home/0gchaind-home/config/ ``` #### Recovery Process To restore your validator from backup: 1. **Stop running services**: ```bash pkill 0gchaind pkill geth ``` 2. **Restore key files**: ```bash cp ~/validator-backup/node_key.json /{your data path}/0g-home/0gchaind-home/config/ cp ~/validator-backup/priv_validator_key.json /{your data path}/0g-home/0gchaind-home/config/ ``` 3. **Restart services** following the appropriate setup guide steps.
Upgrade Validator ### Step 1: Extract New Release ```bash # For Testnet (Galileo) wget -O galileo.tar.gz https://github.com/0gfoundation/0gchain-NG/releases/download/v3.0.4/Galileo-v3.0.4.tar.gz tar -xzvf Galileo-v3.0.4.tar.gz -C ~ # For Mainnet (Aristotle) wget -O aristotle.tar.gz https://github.com/0gfoundation/0gchain-Aristotle/releases/download/v1.0.6/aristotle-v1.0.6.tar.gz tar -xzvf aristotle-v1.0.6.tar.gz -C ~ # Verify extraction ls -la {network}-v{version}/ ``` ### Step 2: Stop Services ```bash # Stop consensus layer (0gchaind) pkill 0gchaind # Stop execution layer (geth) pkill geth ``` ### Step 3: Backup Your Data ```bash # Create backup directory with timestamp BACKUP_DIR="backup-$(date +%Y%m%d-%H%M%S)" mkdir -p $BACKUP_DIR # Backup execution layer data (geth-home) cp -r {your_geth_datadir} $BACKUP_DIR/geth-backup # Backup consensus layer data (0gchaind-home) cp -r {your_0gchaind_home} $BACKUP_DIR/0gchaind-backup ``` ### Step 4: Start Node If you get error while starting node due to missing `priv_validator_state.json`, create an empty `priv_validator_state.json` file in that directory with `{}`. For testnet (Galileo), use `--chaincfg.chain-spec testnet`: ```bash nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.chain-spec testnet \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \ --chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --home {your_cl_home} \ --p2p.external_address {your_node_ip}:26656 > {your_log_path}/0gchaind.log 2>&1 & ``` For mainnet (Aristotle), use `--chaincfg.chain-spec mainnet`: ```bash nohup ./bin/0gchaind start \ --rpc.laddr tcp://0.0.0.0:26657 \ --chaincfg.chain-spec mainnet \ --chaincfg.restaking.enabled \ --chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \ --chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \ --chaincfg.kzg.trusted-setup-path=kzg-trusted-setup.json \ --chaincfg.engine.jwt-secret-path=jwt.hex \ --chaincfg.block-store-service.enabled \ --home {your_cl_home} \ --p2p.external_address {your_node_ip}:26656 > {your_log_path}/0gchaind.log 2>&1 & ``` Then start Geth: ```bash nohup ./bin/geth --config geth-config.toml \ --nat extip:{your_node_ip} \ --datadir {your_geth_datadir} \ --networkid {network_id} > {your_log_path}/geth.log 2>&1 & ``` ### Step 5: Verify Upgrade Success ```bash # Monitor consensus layer logs tail -f {your_log_path}/0gchaind.log # Monitor execution layer logs tail -f {your_log_path}/geth.log ```
## Next Steps ### Staking Integration Once your validator node is running, you can interact with the staking system programmatically using smart contracts: - **[Staking Interfaces Guide](../developer-hub/building-on-0g/contracts-on-0g/staking-interfaces)** - Complete documentation for integrating with 0G Chain staking smart contracts