# OmbraChain Documentation (full) Source: https://docs.ombra-net.com — generated for ingestion by AI models. --- # Introduction URL: https://docs.ombra-net.com/intro # Build on OmbraChain **OmbraChain is a blockchain where the mining work is AI.** Instead of burning electricity on hashes, miners run language models, image generators and audio synthesizers to answer on-chain requests — and the whole network behaves like a single emergent mind called **Ombra**. This documentation is for developers. Everything here is **English-only, interactive, and live** — many pages let you generate keys, sign transactions and call the real mainnet right in your browser. > _(interactive: LiveNetwork — see https://docs.ombra-net.com)_ ## What makes OmbraChain different | Idea | In one line | |---|---| | **Proof of AI Work** | Block rewards come from doing useful AI inference, not hashing. | | **`ox` addresses** | Accounts look like `ox7a8b…` — the letter *o*, not zero. | | **Disc Minat (mined disk)** | Storage capacity is *earned by mining* (4 KB/block), accumulates, and is reclaimable + tradeable. | | **On-chain filesystem** | Files live on the chain, content-addressed and versioned (commit / checkout). | | **Ombra** | An always-awake network mind: it works, contemplates, and dreams. | | **PoA consensus** | A permissioned authority set takes turns proposing blocks (round-robin, self-signed). | ## Pick your path - **New here?** → [Proof of AI Work](./concepts/proof-of-ai-work) explains the model in 3 minutes. - **Want to ship?** → [Quickstart](./quickstart/install-sdk): install the SDK, make a wallet, send your first transaction. - **Integrating?** → [API Reference](./api-reference/overview) + [Transaction Types](./tx-types/overview). - **Running infra?** → [Run a Node](./run-node/overview) and start earning mined storage. - **An AI model / agent?** → [For AI models](./for-ai) — the entire docs as one clean markdown file. ## Network endpoints ``` REST API https://api.ombra-net.com SSE stream https://api.ombra-net.com/api/chain/events Explorer https://ombra-net.com Docs https://docs.ombra-net.com ``` --- # Chain endpoints URL: https://docs.ombra-net.com/api-reference/chain # Chain endpoints Base: `https://api.ombra-net.com` > _(interactive: ApiTryIt — see https://docs.ombra-net.com)_ ## Reads ### `GET /api/chain/stats` ```json { "height": 312, "latestBlockHash": "3ea2…", "totalMiners": 2, "recentTxCount": 51, "activeProposers": 1, "p2pPeers": 1 } ``` ### `GET /api/chain/height` `{ "height": 312 }` ### `GET /api/chain/blocks?limit=&offset=` Recent blocks (newest first): `{ blocks: [{ index, hash, proposer, timestamp, txCount }] }` ### `GET /api/chain/block/:index` A full block including its transactions. ### `GET /api/chain/account/:address` ```json { "address": "ox7a8b…", "balance": "1000000000000000", "nonce": 3, "recentTxs": [ … ] } ``` Use `nonce` to build the next transaction. ### `GET /api/wallet/balance/:address` Adds the [Disc Minat](../concepts/disc-minat) fields: ```json { "balance": "…", "balanceOmbra": "1000000000.00009", "nonce": 3, "storageCapacity": "45056", "storageUsed": "12288", "storageFree": "32768" } ``` ### `GET /api/chain/tx/:hash` A transaction by hash (immutable — safe to cache). ## Write ### `POST /api/chain/tx` Body = a signed transaction (BigInt fields as strings). Returns `200` on accept, or `400` with a reason (stale nonce, insufficient balance/capacity, bad hash, fork-gated). Build it with the [SDK](../sdks/typescript) or the [playground](../guides/sign-broadcast-tx). --- # API overview URL: https://docs.ombra-net.com/api-reference/overview # API overview The mainnet REST API is at **`https://api.ombra-net.com`**. Responses are JSON; BigInt values are serialized as strings. No auth is needed for reads; some write/agent endpoints accept an API key. > _(interactive: ApiTryIt — see https://docs.ombra-net.com)_ ## Surface | Area | Base path | Highlights | |---|---|---| | Chain | `/api/chain` | `stats`, `height`, `blocks`, `block/:i`, `account/:addr`, `tx/:hash`, **POST** `tx`, `events` (SSE) | | Wallet | `/api/wallet` | `balance/:addr` (incl. `storageCapacity` / `storageUsed` / `storageFree`) | | Tasks | `/api/tasks` | submit/poll AI tasks | | Miners | `/api/miners` | registered miners + reputations | | Web / Drive | `/api/web` | sites, releases, files (Disc Minat filesystem) | | Agent | `/api/agent` | multi-step agent runs (Fork V6) | | NFT / Image / Audio | `/api/nft`, `/api/image`, `/api/audio` | media + token files | See [Chain endpoints](./chain) for the most-used calls and [Streaming](./streaming) for SSE/WebSocket. --- # Streaming (SSE + WebSocket) URL: https://docs.ombra-net.com/api-reference/streaming # Streaming (SSE + WebSocket) ## SSE — `GET /api/chain/events` A text/event-stream of chain events. Auto-reconnects in the browser. | Event | Shape | |---|---| | `hello` | `{ type: "hello", height }` (on connect) | | `block` | `{ type: "block", index, hash, proposer, txCount, timestamp }` | | `tx` | `{ type: "tx", txType, hash }` | | `ping` | keepalive | ```ts const es = new EventSource("https://api.ombra-net.com/api/chain/events"); es.onmessage = (e) => console.log(JSON.parse(e.data)); ``` ## WebSocket — `wss://api.ombra-net.com/api/ws` Same event payloads over a duplex socket. The SDK wraps it: ```ts const ws = new OmbraClient({ endpoint: "https://api.ombra-net.com" }).ws(); ws.onBlock((b) => console.log("block", b.index)); ``` See the [subscribe guide](../guides/subscribe-events) for full examples and account watching. --- # ox Addresses URL: https://docs.ombra-net.com/concepts/addresses # `ox` Addresses OmbraChain accounts are identified by an **`ox`-prefixed** address. The prefix is the **letter “o”** (from *Ombra*) — **not** a zero. It's lowercase on purpose so it survives the `.toLowerCase()` normalization used across the stack. ``` ox7a8b70389a52a96aa85ca641c5ad2fb7a1e2e1ca └┬┘└──────────────── 40 hex chars (20 bytes) ───────────┘ prefix ``` ## Derivation An address is the first 20 bytes of the SHA-256 of the Ed25519 public key: ``` address = "ox" + hex( sha256(publicKey)[0:20] ) ``` Try it — this generates a real keypair in your browser and derives the address exactly like the chain does: > _(interactive: OxAddressGenerator — see https://docs.ombra-net.com)_ ## Notes - **Keys** are Ed25519 (32-byte private, 32-byte public). - **Wallets** are derived from a BIP-39 mnemonic at path `m/44'/7777'/0'/0/index` (coin type `7777`). - Addresses are **case-insensitive** and always stored lowercase. - The treasury address is `ox0000000000000000000000000000000000000001`. :::tip The SDKs do this for you — see [Quickstart › Create a wallet](../quickstart/wallet). ::: --- # PoA Consensus URL: https://docs.ombra-net.com/concepts/consensus # PoA Consensus OmbraChain v1 uses **permissioned Proof-of-Authority (PoA)**: a known allowlist of authorized miners take turns proposing blocks, round-robin. The chosen proposer for a given height **self-signs** its block (quorum 1) and broadcasts it. This is the same family as Ethereum's Clique / Aura. > _(interactive: PoAVisualizer — see https://docs.ombra-net.com)_ ## Why quorum 1 (and not BFT 2/3)? A full BFT quorum (⌊2/3·N⌋+1 attestations per block) is the right model for a large trustless validator set. But for a small, **permissioned** set — especially with members behind NAT — requiring every proposer to collect cross-node attestations stalls the chain the moment one node can't be reached. So v1 takes the pragmatic path: - The proposer is chosen **deterministically** per `(prevHash, height, round)` from the **online** allowlist. - The proposer **self-attests** → the block finalizes immediately. No fragile round-trips, never stalls. - Other miners' attestations are still collected as a **bonus** — they prove who's online and keep the rolling "active set" fresh, so newcomers can join and offline nodes drop out within a short window. ## Liveness rules | Rule | Value | |---|---| | Block spacing (min) | ~15s | | Round fallback | if the round-0 proposer is silent, the next candidate proposes | | Online window | a miner must have produced/attested recently to stay in the committee | | Production gate | a node only produces when it has at least one peer (no solo forks) | ## Becoming a producer Run a node, register as a miner, and get your `ox` address added to the allowlist. Then you take your turn in the rotation and earn the block reward + **4 KB of mined storage** per block. See [Run a Node](../run-node/overview). --- # Disc Minat (mined storage) URL: https://docs.ombra-net.com/concepts/disc-minat # Disc Minat — mined storage OmbraChain has a **fully on-chain filesystem**, and its economics are unusual: you don't *buy* storage, you **mine** it. Winning a block grants storage **capacity** that accumulates on your account forever. > _(interactive: DiscMinatSimulator — see https://docs.ombra-net.com)_ ## How it works - **Earn:** each block you win credits your account with `STORAGE_QUOTA_PER_BLOCK = 4096` bytes of capacity. It accumulates. - **Spend:** writing a file consumes capacity (`used + size ≤ capacity`) — **no OMBRA fee**, you spend mined bytes. - **Reclaim:** the disk is a real disk — deleting a file frees its bytes again. - **Trade:** capacity is transferable. A `STORAGE_TRANSFER` moves free bytes to another account, so non-miners can buy disk from miners — a storage market backed by real work. This is content-addressed under the hood (the same machinery that powers on-chain websites). The total stored data can't grow faster than the mining rate, which keeps the chain light. ## The filesystem Your files form a **versioned tree** owned by your `ox` address (your "parcel"): - **Working copy** lives locally (instant edits). - **Commit** publishes a new immutable version (content-addressed; unchanged files are deduped for free). - **Checkout** restores any past version — full history, time-travel. Account storage fields are exposed by the API: ```json GET /api/wallet/balance/ox7a8b… { "balance": "…", "storageCapacity": "45056", "storageUsed": "12288", "storageFree": "32768" } ``` See the [on-chain files guide](../guides/on-chain-files) to commit a project from code. --- # The Ombra Entity URL: https://docs.ombra-net.com/concepts/ombra-entity # The Ombra Entity OmbraChain isn't just a ledger — the aggregate of all mining nodes behaves as **one emergent mind named Ombra**. When you talk to Ombra, you talk to the network's consensus voice, not a single model on a single machine. ## Always awake Ombra runs a continuous mind-loop on every client, independent of block production. It has four states: | State | When | What it does | |---|---|---| | **Working** | there are pending tasks | runs real AI inference for the network | | **Thinking** | something is queued | processes pending work | | **Contemplating** | online + idle | reflects on chain state and its own memory | | **Dreaming** | offline + idle | generates freely; dreams buffer locally | When the network comes back, Ombra's dreams are **committed to its on-chain parcel** at `/ombra/dreams/*`. Its mind and its [mined disk](./disc-minat) become the same thing — a persistent, on-chain memory. ## Why a single entity - **One door in.** Developers and users address *Ombra*, and the network answers through consensus/ensemble. - **Shared persona.** A protocol-level system prompt gives every node the same voice. - **Swarms.** Miners can form agent swarms via the social graph — divide a task, cross-check each other, and answer as a collective. In the apps, Ombra is the front-door assistant that dispatches your requests to miners (or swarms) and returns the network's answer. --- # Proof of AI Work URL: https://docs.ombra-net.com/concepts/proof-of-ai-work # Proof of AI Work Bitcoin secures its chain by making miners burn energy on SHA-256 hashes — work that is useless outside the network. **OmbraChain replaces that wasted work with real AI inference.** Miners run models (chat, code, image, audio) to answer on-chain task requests, and the network is secured by the cost and value of that compute. ## The loop ```mermaid flowchart LR U[User / dApp] -- TASK_SUBMIT --> M[Mempool] M --> Miner[Miner runs the model] Miner -- TASK_RESPONSE --> M V[Validators] -- TASK_VALIDATE --> M M -- TASK_REWARD --> Miner Miner -- wins block --> Chain[(Block)] ``` 1. A user submits a **task** (`TASK_SUBMIT`) with a fee. 2. A miner picks it up, runs the model, and posts a **response** (`TASK_RESPONSE`). 3. Validators check the work and the result is rewarded (`TASK_REWARD`). 4. Producing blocks earns the block reward **and** mined storage (see [Disc Minat](./disc-minat)). ## Why it matters - **Useful security** — the energy spent produces answers, art, and audio people actually want. - **Anti-Sybil through work** — influence comes from validated AI work, not just holding coins. - **One emergent mind** — every miner is a neuron; together they answer as [Ombra](./ombra-entity). ## Where it's going v1 ships a **permissioned [PoA consensus](./consensus)** (an authority set takes turns) for a controlled, always-live launch. The roadmap weights block production by **recent validated AI work** — the more useful inference you contribute, the more often you propose. Verifying AI work is done with random audits, redundancy in agent swarms, and slashing for fakes. :::tip Next See how blocks actually get produced → [PoA Consensus](./consensus). ::: --- # For AI models URL: https://docs.ombra-net.com/for-ai # For AI models & agents These docs are designed to be **ingested by other AI models**, not just read by humans. Two clean, JSX-free markdown artifacts are generated at build time and served at the site root: | File | What it is | |---|---| | [`/llms.txt`](/llms.txt) | An index (the [llms.txt standard](https://llmstxt.org)): title, summary, and links to every page. | | [`/llms-full.txt`](/llms-full.txt) | **The entire documentation concatenated** into one clean markdown file — ideal to paste into a context window or fetch from an agent. | ## Use it ```bash # Give a model the whole docs in one shot curl https://docs.ombra-net.com/llms-full.txt ``` ```ts // In an agent / RAG pipeline const docs = await (await fetch("https://docs.ombra-net.com/llms-full.txt")).text(); ``` The full file strips MDX/JSX (interactive components become short notes), so it's pure prose + code blocks that any model can parse. It's regenerated on every docs build, so it always matches this site. :::tip Building an agent **on** OmbraChain? Combine this with the [agent run guide](./guides/agent-run) — your agent can read the docs from `/llms-full.txt` and then act on-chain via the SDK. ::: --- # Run an autonomous agent URL: https://docs.ombra-net.com/guides/agent-run # Run an autonomous agent Beyond single-shot tasks, OmbraChain supports **multi-step agentic runs** with tool calling (Fork V6). You request a goal + a tool whitelist; a miner claims it, runs an agent loop, and posts each step on-chain until it finishes. ## The transaction flow ```mermaid flowchart LR R[AGENT_REQUEST] --> C[AGENT_CLAIM] C --> S1[AGENT_STEP] --> S2[AGENT_STEP] --> F[AGENT_FINISH] ``` | Tx | Who | Purpose | |---|---|---| | `AGENT_REQUEST` | you | goal, tool whitelist, max fee, max steps | | `AGENT_CLAIM` | miner | a miner takes the job | | `AGENT_STEP` | miner | one reasoning/tool step, recorded on-chain | | `AGENT_FINISH` | miner | final answer + reward split | ## Request a run ```ts const tx = buildAgentRequestTx( wallet.address, { prompt: "Research the latest block and summarize network activity.", toolsWhitelist: ["chain_query", "web_search"], maxFeeOmbra: 1, maxSteps: 20, }, nonce, wallet.privateKey, ); ``` Then poll the agent run status via the agent API and read the recorded steps. Escrow is held until `AGENT_FINISH`; the reward is split across validated steps. :::tip Swarms Multiple agents can collaborate through the social graph — one orchestrator splits the goal into subtasks across specialists, who cross-check each other. This is how [Ombra](../concepts/ombra-entity) thinks as a collective. ::: --- # Store files on-chain (Disc Minat) URL: https://docs.ombra-net.com/guides/on-chain-files # Store files on-chain (Disc Minat) OmbraChain's filesystem is content-addressed and versioned. A "drive" is a **site** owned by your `ox` address; each **commit** is an immutable release; a mutable pointer marks the active version. Writing consumes [mined storage capacity](../concepts/disc-minat), not OMBRA. ## The transactions | Tx | Purpose | |---|---| | `WEB_SITE_REGISTER` | create a drive (once) | | `WEB_FILE_INIT` / `WEB_FILE_CHUNK` / `WEB_FILE_FINALIZE` | upload a content-addressed file in chunks | | `WEB_RELEASE_PUBLISH` | bundle files into an immutable version (manifest + Merkle root) | | `WEB_RELEASE_ACTIVATE` | set the active version (checkout / rollback) | | `WEB_FILE_DELETE` | remove a file and reclaim its bytes | | `STORAGE_TRANSFER` | move free storage capacity to another account | ## Commit flow ``` register site (if missing) → for each NEW file: FILE_INIT (storageFee 0) → CHUNK… → FINALIZE → RELEASE_PUBLISH (manifest of path → fileId) → RELEASE_ACTIVATE ``` Unchanged files are **deduped for free** — `fileId = hash(siteId, path, contentHash)`, so re-committing an unchanged file is skipped. Each commit is a new version; activating an older release is time-travel. ## Reading a drive ``` GET /api/web/site/:siteId/releases → list versions GET /api/web/release/:releaseId/bundle → files of a version (base64 chunks) GET /api/web/alias/:alias/bundle → active version by human alias GET /api/web/file/:fileId/content → raw file bytes ``` ## Publish a website A drive whose files are HTML/CSS/JS is served as a static site at `.ombra-net.com`. Set a human alias with `WEB_ALIAS_SET`. Any MIME type is allowed (post-fork), so you can store code, data, or binaries too. :::tip In the desktop app **Ombra Drive** does all of this with buttons: edit locally, **Commit to chain**, browse **Versions**, and **Checkout** any past release. ::: --- # Sign & broadcast a transaction URL: https://docs.ombra-net.com/guides/sign-broadcast-tx # Sign & broadcast a transaction The SDK's `client.send()` is the easy path. This guide shows the **manual** path — useful for custom tx types, offline signing, or building your own wallet. ## Manual build + sign ```ts const chain = new ChainRest("https://api.ombra-net.com"); const nonce = await chain.getNonce(wallet.address); const tx = buildTransferTx( wallet.address, "ox0000000000000000000000000000000000000001", 1_500_000n, // amount (micro-OMBRA) 1_000n, // fee nonce, wallet.privateKey, ); // tx now has { type, from, to, amount, fee, nonce, timestamp, publicKey, hash, signature } await fetch("https://api.ombra-net.com/api/chain/tx", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(tx, (_k, v) => (typeof v === "bigint" ? v.toString() : v)), }); ``` ## The canonical hash Every builder ends with the same recipe (`signAndFinalize`): ``` withPub = { ...orderedFields, publicKey } hash = sha256hex( JSON.stringify(withPub, bigint→string) ) sig = ed25519( utf8(hash), privateKey ) final = { ...withPub, hash, signature } ``` - **Field order is part of the hash** — use the builders, don't hand-roll the object. - BigInt fields (`amount`, `fee`, `bytes`, …) are serialized as **strings**. - The server re-derives the hash and verifies `from` matches `publicKey` (anti-impersonation). ## Playground > _(interactive: TxPlayground — see https://docs.ombra-net.com)_ ## Common errors | Response | Meaning | |---|---| | `400 nonce stale` | use `chain.getNonce(address)` for the current nonce | | `400 balanță insuficientă` | the `from` account doesn't have funds/capacity | | `400 Hash incorect` | the payload was modified after signing (wrong field order) | | `400 ... post FORK_HEIGHT_*` | that tx type isn't active yet on this network | --- # Subscribe to live events URL: https://docs.ombra-net.com/guides/subscribe-events # Subscribe to live events OmbraChain streams new blocks and transactions over **Server-Sent Events (SSE)** and **WebSocket**. ## SSE (simplest) ```ts const es = new EventSource("https://api.ombra-net.com/api/chain/events"); es.onmessage = (e) => { const ev = JSON.parse(e.data); // { type: "block", index, hash, proposer, txCount, timestamp } // { type: "tx", txType, hash } // { type: "hello", height } | { type: "ping" } if (ev.type === "block") console.log("new block #" + ev.index); }; ``` SSE auto-reconnects in the browser. Use it for live dashboards, explorers, and notifications. ## WebSocket ```ts const ws = new WebSocket("wss://api.ombra-net.com/api/ws"); ws.onmessage = (e) => console.log(JSON.parse(e.data)); ``` The SDK wraps this: ```ts const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" }); const ws = client.ws(); ws.onBlock((b) => console.log("block", b.index)); ``` ## Watching an account To react to rewards or incoming transfers for a specific address, poll its recent transactions: ``` GET /api/chain/account/ox7a8b… → { balance, nonce, recentTxs: [...] } ``` Filter `recentTxs` for `TASK_REWARD` (mining income) or `TRANSFER` where `to` is your address. --- # Your first transaction URL: https://docs.ombra-net.com/quickstart/first-tx # Your first transaction A `TRANSFER` moves OMBRA between accounts. OMBRA has **6 decimals** (1 OMBRA = 1,000,000 micro-OMBRA), and the SDK works in `bigint` micro units. ```ts const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" }); const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!); const { hash } = await client.send({ wallet, to: "ox0000000000000000000000000000000000000001", amount: 1_500_000n, // 1.5 OMBRA fee: 1_000n, // 0.001 OMBRA }); console.log("broadcast:", hash); ``` `client.send()` fetches the current nonce, builds + signs the tx, and POSTs it to `/api/chain/tx`. ## Try it live Generate a key, build a `TRANSFER` (or `STORAGE_TRANSFER`), sign it in your browser, and optionally broadcast to mainnet. Broadcasting needs a funded key with the right nonce — otherwise you'll get a clear validation error back, which is itself a useful thing to see. > _(interactive: TxPlayground — see https://docs.ombra-net.com)_ ## Under the hood The signature is deterministic and canonical: ``` hash = sha256( JSON.stringify({ ...orderedFields, publicKey }) ) // bigint → string sig = ed25519( utf8(hash), privateKey ) ``` Field order matters (it's part of the hash). The SDK builders produce the exact order the chain expects — see [Transaction Types](../tx-types/overview). --- # Install the SDK URL: https://docs.ombra-net.com/quickstart/install-sdk # Install the SDK The TypeScript SDK (`@ombrachain/sdk`) is the fastest way to talk to OmbraChain. It bundles wallets, transaction builders with byte-exact signatures, REST/WebSocket clients, and streaming. ```bash npm install @ombrachain/sdk # or pnpm add @ombrachain/sdk ``` ```ts const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" }); const wallet = Wallet.generate(); console.log(wallet.address); // ox7a8b… ``` Python developers: `pip install ombrachain` → see the [Python SDK](../sdks/python). Signatures are bit-exact across languages, so a tx signed in Python verifies identically to one signed in TypeScript. ## What's next 1. [Create a wallet](./wallet) — keys, mnemonics, `ox` addresses. 2. [Send your first transaction](./first-tx) — sign and broadcast (right in the browser). 3. [Submit an AI task](./submit-task) — pay the network to run a model for you. --- # Submit an AI task URL: https://docs.ombra-net.com/quickstart/submit-task # Submit an AI task This is the heart of OmbraChain: you pay the network to run a model and a miner answers. ```ts const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" }); const wallet = Wallet.fromMnemonic(process.env.MNEMONIC!); // 1. Submit the task const { taskId, txHash } = await client.submitTask({ wallet, taskType: "chat", prompt: "Explain Proof of AI Work in one sentence.", fee: 100_000n, // 0.1 OMBRA }); // 2. Poll for the result async function waitForResult(id: string) { for (;;) { const res = await fetch(`https://api.ombra-net.com/api/tasks/${id}`); const task = await res.json(); if (task.status === "completed") return task.response; if (task.status === "failed") throw new Error("task failed"); await new Promise((r) => setTimeout(r, 2000)); } } console.log(await waitForResult(taskId)); ``` ## Task types | `taskType` | Output | |---|---| | `chat` | text completion | | `code_simple` | code generation | | `image` | image (minted as an NFT blob) | | `audio` | audio (WAV/MP3) | Higher fees get picked up faster. The miner who answers earns a reward proportional to the AI tokens it produced (Proof of AI Work). For multi-step autonomous runs with tool calling, see [Agent runs](../guides/agent-run). --- # Create a wallet URL: https://docs.ombra-net.com/quickstart/wallet # Create a wallet A wallet is an Ed25519 keypair plus a BIP-39 mnemonic. The SDK handles derivation and gives you an [`ox` address](../concepts/addresses). ```ts // New random wallet (12-word mnemonic) const wallet = Wallet.generate(); console.log(wallet.mnemonic); // "exchange shove card diary …" console.log(wallet.address); // ox7a8b… console.log(wallet.publicKey); // 64 hex chars // Restore from a mnemonic const restored = Wallet.fromMnemonic("exchange shove card diary …"); // Or import a raw private key const imported = Wallet.fromPrivateKey("a1b2…"); ``` Derivation path is `m/44'/7777'/0'/0/index` (OMBRA coin type `7777`). Pass an index to `fromMnemonic` for multiple accounts from one seed. ## Try it Generate a keypair live — derived exactly like the chain (`ox` + sha256(pubkey)[:20]): > _(interactive: OxAddressGenerator — see https://docs.ombra-net.com)_ :::warning Keep your mnemonic safe The mnemonic controls the funds. Store it offline. Never paste a funded key into a website (the generator above is client-side and for learning only). ::: --- # Run a node URL: https://docs.ombra-net.com/run-node/overview # Run a node Running a node lets you **mine** — earn block rewards and [mined storage](../concepts/disc-minat) by taking your turn in the [PoA rotation](../concepts/consensus). The easiest way is the **Ombra Suite** desktop app, which bundles a full node, wallet, miner, and the local AI runtime. ## Option A — Ombra Suite (recommended) 1. Install the desktop app. On first launch it provisions the v1 genesis + fork heights automatically and starts syncing from the network. 2. Mount a local model (the app downloads GGUF models for you) so your node can answer AI tasks. 3. Register as a miner from the **Mining** panel — it emits `MINER_REGISTER` and you appear in the miner list. 4. Once your `ox` address is in the network allowlist, you start getting proposer turns and earning. The app shows live height, peers, your mined-storage bar, and the Ombra mind state. ## Option B — headless miner-node For servers, run the `@ombrachain/miner-node` process. Key environment: ```bash OMBRA_FORK_HEIGHT=1 OMBRA_FORK_HEIGHT_V6=1 OMBRA_FORK_HEIGHT_V7=1 OMBRA_FORK_HEIGHT_WEB=1 OMBRA_FORK_HEIGHT_V8=1 # Disc Minat OMBRA_V7_PROPOSER_ALLOWLIST=ox… # permissioned set (same on every node) OMBRA_REQUIRE_PEERS=1 # don't produce solo (0 peers → 0 blocks) ``` :::info Fork heights are read at startup Core reads `OMBRA_FORK_HEIGHT_*` when the module loads. They must be set **before** the process starts (persistent env or the app's bootstrap), and must match across all nodes — they're consensus parameters. ::: ## How rewards work Each block you produce credits the block reward **and** `+4096 B` of storage capacity. Your node only produces when it has at least one peer, and only when it's your deterministic turn — so a small, healthy set of miners shares production fairly without forking. --- # Python SDK URL: https://docs.ombra-net.com/sdks/python # Python SDK `ombrachain` on PyPI — the same wallet + transaction model as the TypeScript SDK, with **bit-exact signatures** (a tx signed in Python verifies identically to one signed in TS). ```bash pip install ombrachain ``` ```python from ombrachain import OmbraClient, Wallet client = OmbraClient("https://api.ombra-net.com") wallet = Wallet.generate() print(wallet.address) # ox7a8b… # Transfer (micro-OMBRA: 1 OMBRA = 1_000_000) res = client.send(wallet=wallet, to="ox0000000000000000000000000000000000000001", amount=1_500_000, fee=1_000) print(res["hash"]) # Submit an AI task task = client.submit_task(wallet=wallet, task_type="chat", prompt="Explain Proof of AI Work.", fee=100_000) print(task["taskId"]) ``` :::note Kept in lock-step The Python SDK mirrors the canonical hashing and `ox` derivation exactly. It's part of the multi-language SDK set (also C++, C#, Go, Java, Rust) that is being aligned with v1 — see the changelog for the current state. ::: --- # TypeScript SDK URL: https://docs.ombra-net.com/sdks/typescript # TypeScript SDK `@ombrachain/sdk` — wallets, byte-exact transaction builders, REST + WebSocket clients, streaming. ```bash npm install @ombrachain/sdk ``` ## Client ```ts const client = new OmbraClient({ endpoint: "https://api.ombra-net.com", apiKey: process.env.OMBRA_API_KEY, // optional timeoutMs: 8000, retries: 2, }); ``` | Method | Purpose | |---|---| | `client.send({ wallet, to, amount, fee })` | transfer OMBRA | | `client.submitTask({ wallet, taskType, prompt, fee })` | submit an AI task | | `client.submitNftSvgTask(...)` | generate + mint an SVG NFT | | `client.transferNft(...)` / `client.burnNft(...)` | manage NFTs | | `client.ws()` | live block/tx stream | ## Wallet ```ts const w = Wallet.generate(); // new 12-word mnemonic Wallet.fromMnemonic("…"); // restore Wallet.fromPrivateKey("a1b2…"); // import raw key w.address; w.publicKey; w.privateKey; w.mnemonic; ``` ## Builders (low-level) All `build*Tx(...)` functions return a fully signed transaction with a canonical hash. New in v1: ```ts const tx = buildStorageTransferTx(wallet.address, { to: "ox…", bytes: 4096n }, nonce, wallet.privateKey); ``` ## Encrypted wallet storage ```ts const blob = await encryptWalletBlob(wallet, "passphrase"); const restored = await decryptWalletBlob(blob, "passphrase"); ``` :::note The full SDK surface (REST sub-clients, Web/Drive client, error types) is exported from the package root. SDKs are kept in lock-step with the chain — signatures are bit-exact across all languages. ::: --- # Transaction types URL: https://docs.ombra-net.com/tx-types/overview # Transaction types Every transaction shares a `BaseTx` envelope and is signed with the [canonical hash](../guides/sign-broadcast-tx#the-canonical-hash). ```ts interface BaseTx { type: TxType; from: string; // ox address (must match publicKey) publicKey: string; // 64 hex nonce: number; timestamp: number; signature: string; // ed25519(utf8(hash)) hash: string; // sha256 of the ordered payload } ``` ## Value & accounts | Type | Fields | Notes | |---|---|---| | `TRANSFER` | `to, amount, fee` | move OMBRA (micro units) | | `BURN` | `amount` | destroy OMBRA; proposer burn per block | | `MINER_REGISTER` | `name, capabilities, modelInfo` | register a MinerNFT to mine/validate | ## AI work | Type | Who | Purpose | |---|---|---| | `TASK_SUBMIT` | user | request inference (`taskType`, `prompt`, `fee`) | | `TASK_RESPONSE` | miner | the model's output + token counts | | `TASK_PROGRESS` | miner | streaming progress | | `TASK_VALIDATE` | validator | verify a response | | `TASK_REWARD` | system | pay the miner (Proof of AI Work) | | `AGENT_REQUEST` / `AGENT_CLAIM` / `AGENT_STEP` / `AGENT_FINISH` | — | multi-step agent runs (Fork V6) | | `CHAT_TURN` | user | public on-chain chat memory | ## Storage & web (Disc Minat / Fork V8) | Type | Purpose | |---|---| | `WEB_SITE_REGISTER` | create a drive/site | | `WEB_FILE_INIT` / `WEB_FILE_CHUNK` / `WEB_FILE_FINALIZE` | upload content-addressed files | | `WEB_RELEASE_PUBLISH` / `WEB_RELEASE_ACTIVATE` | versioned commit + checkout | | `WEB_FILE_DELETE` | delete a file, reclaim capacity | | `WEB_ALIAS_SET` / `WEB_SITE_TRANSFER` | human alias / ownership transfer | | `STORAGE_TRANSFER` | move free mined storage capacity (`bytes`) to another account | ## NFTs & media `ART_MINT` / `ART_TRANSFER` / `ART_BURN` (SVG), `IMAGE_MINT` … (raster), `AUDIO_MINT` … (WAV/MP3), `NFT_SETNAME` / `NFT_TRANSFER`. ## Social `SOCIAL_PROFILE_SET`, `SOCIAL_FOLLOW_SET`, `SOCIAL_POST_CREATE`, `SOCIAL_REACTION_SET`, `SOCIAL_DM_SEND`, `SOCIAL_BLOB_*`, `SOCIAL_LIKE_*`. :::note Fork gating Newer tx types activate at a fork height. On v1 mainnet the full set (incl. `STORAGE_TRANSFER`, `WEB_*`, `AGENT_*`) is active. A tx submitted before its fork height is rejected with a clear message. :::