—
—
—
Stake THRA to participate in Proof-of-Stake validation and secure the network.
Your private key is encrypted with your password and decrypted entirely in your browser — never sent to any server.

A Browser-Native Decentralized Peer-to-Peer Computation Network
Version 1.0 · Technical Whitepaper
thra.network · 2025
THRA Network is a browser-native, fully decentralized peer-to-peer computation network in which every browser session constitutes an autonomous cryptographic node. Each node is assigned a unique Ed25519 identity, participates in a SHA-256 secured Directed Acyclic Graph (DAG) ledger, and communicates directly with peers via WebRTC data channels brokered by a lightweight WebSocket signaling layer. The THRA token serves as the native currency, staking asset, and governance unit. Unlike traditional blockchain networks that require heavyweight client software, THRA operates entirely within the constraints of a standards-compliant web browser using the Web Crypto API, requiring no plugins, extensions, or downloads. This paper describes the full technical architecture, consensus mechanism, token economics, developer SDK, and the rationale for each design decision.
The internet was originally conceived as a decentralized communication fabric — a network of equal peers exchanging data without a central authority. Over time, economic forces concentrated infrastructure into the hands of a small number of large providers. Today, the majority of web applications depend on centralized servers for authentication, state management, and data persistence. This architecture introduces single points of failure, censorship vectors, and data sovereignty concerns that are incompatible with the original ethos of an open web.
THRA Network re-imagines the web browser not as a thin client consuming centralized services, but as a full network node: an autonomous participant capable of generating cryptographic identities, maintaining a local ledger, transacting directly with peers, and contributing to network consensus — all within the sandboxed environment of a standard web browser.
The design philosophy of THRA is grounded in three principles:
THRA is written entirely in TypeScript — both the browser client and the Node.js signaling server — ensuring a unified type system, shared data structures, and a consistent developer experience across the full stack.
Existing public blockchain networks such as Bitcoin and Ethereum offer strong cryptographic guarantees but impose significant participation barriers. Running a full Ethereum node requires downloading hundreds of gigabytes of chain data, maintaining synchronized state against a global peer network, and operating specialized client software. Light clients improve accessibility but sacrifice trustlessness, relying on full nodes to serve state proofs.
Smart-contract platforms have demonstrated that programmable value transfer is commercially viable, but their architectures were designed for desktop and server environments. Browser-based dApp frontends interact with the network through centralized RPC providers (Infura, Alchemy) — reintroducing the centralization that blockchain was intended to remove.
Linear blockchain architectures serialize all transactions into a single chain, fundamentally limiting throughput. DAG-based ledgers such as IOTA's Tangle and Nano's Block Lattice permit multiple vertices to be appended in parallel, improving throughput in proportion to network activity. THRA adopts a DAG structure where each vertex references one or more "tip" vertices as parents, creating a partial order over transactions that allows parallel processing while preserving causal integrity.
The WebRTC standard (RFC 8825) enables browsers to establish low-latency, encrypted peer-to-peer data channels directly, without server mediation. The RTCDataChannel API supports binary and text messaging with sub-100ms round-trip times on local area networks and sub-300ms on intercontinental paths. THRA exploits this to create a mesh network topology in which transaction propagation does not depend on any central relay.
THRA was designed with the following explicit goals:
genesis, transfer, profile, stakeTHRA Network consists of three architectural tiers that operate with clearly defined responsibilities and minimal coupling:
Each browser session instantiates a DecentralizedNode object — the primary SDK class. This object holds the node's Ed25519 key pair in memory (using the non-extractable CryptoKey type provided by the Web Crypto API), maintains a local DAGLedger instance, and manages the SignalingClient which handles all P2P connectivity. The node is self-sufficient: it can verify balances, sign transactions, and propagate updates entirely without contacting any server.
The THRA signaling server (written in TypeScript, running on Node.js) performs two functions: it acts as a WebRTC rendezvous point, relaying ICE offers, answers, and candidates between nodes that cannot yet communicate directly; and it mirrors the DAG ledger to a PostgreSQL database, enabling nodes to retrieve historical transactions on startup, synchronize after offline periods, and serve as light-node data sources. The signaling server never holds private keys and cannot construct or sign transactions.
| Component | Technology | Rationale |
|---|---|---|
| Client runtime | Browser (Chrome/Firefox/Safari) | Zero-install, universal access |
| Client language | TypeScript → ES2022 | Type safety, modern browser targets |
| Server language | TypeScript (Node.js) | Shared types with client SDK |
| Cryptography | Web Crypto API (Ed25519, SHA-256) | Native browser, no external deps |
| P2P transport | WebRTC RTCDataChannel | Browser-native direct P2P |
| Signaling | WebSocket (ws library) | Low latency connection brokering |
| Persistence | PostgreSQL | ACID transactions, JSONB vertex storage |
| Build tool | esbuild | Sub-second TypeScript bundling |
| Ledger structure | Directed Acyclic Graph | Parallel transaction processing |
Upon account creation, THRA generates an Ed25519 key pair using the browser's crypto.subtle.generateKey method with the Ed25519 algorithm. Ed25519 was selected over ECDSA (secp256k1) for the following reasons:
A node's identity is defined as the SHA-256 hash of its DER-encoded public key, represented as a 64-character lowercase hexadecimal string. This Node ID serves as the node's primary identifier across all network operations. It is stable for the lifetime of the key pair and can be recomputed from the public key at any time.
nodeId = SHA-256( DER-encode( Ed25519PublicKey ) ).toHex()
The wallet address is derived as a prefix-checksum of the node ID, providing a shorter human-readable identifier for token transfer operations:
walletAddress = "thra" + nodeId.substring(0, 40)
The private key is exported in PKCS#8 DER format, encrypted with the user's password using AES-GCM (256-bit key derived via PBKDF2 with 100,000 iterations and SHA-256), and stored in the server-side PostgreSQL database. The plaintext private key is never transmitted over the network and exists only in browser memory during an active session. The Web Crypto API's extractable: false flag prevents raw key extraction via JavaScript reflection after the key is imported.
Every transfer vertex includes an Ed25519 digital signature over the transaction payload string:
signingPayload = "transfer:" + fromNodeId + ":" + toNodeId + ":" + amount + ":" + timestamp
signature = Ed25519.sign( signingPayload, privateKey )
The signature and a SHA-256 hash of the signing payload are embedded in the vertex's data field, enabling any participant to verify authenticity without trusting the sender.
The THRA ledger is a Directed Acyclic Graph in which each node is a vertex with the following structure:
interface DagVertex {
id: string // Unique vertex identifier
parentIds: string[] // References to parent vertex IDs (tips at creation time)
type: VertexType // 'genesis' | 'transfer' | 'profile' | 'stake'
timestamp: number // Unix milliseconds
from: string // Originating node ID
to?: string // Destination node ID (transfers only)
amount?: number // THRA amount (genesis/transfer/stake)
data?: object // Type-specific metadata
hash: string // SHA-256 of canonical JSON representation
}
Each vertex's integrity hash is computed as the SHA-256 of the canonical JSON representation of all fields except hash itself:
hashInput = JSON.stringify({
id, parentIds, type, timestamp, from, to, amount, data
})
vertex.hash = await crypto.subtle.digest('SHA-256', encode(hashInput))
This hash serves as a content address: any mutation of the vertex data, however small, produces a completely different hash, making tampering immediately detectable.
| Type | Description | Parents | Amount |
|---|---|---|---|
genesis | Initial allocation — created once per node on first initialization | [] (none) | 50 THRA |
transfer | Value transfer between two nodes; carries Ed25519 signature | Current DAG tips | Arbitrary |
profile | Node identity metadata update (display name, etc.) | Current DAG tips | None |
stake | Commits THRA balance to the validator stake pool | Current DAG tips | Staked amount |
A tip is a vertex that has not yet been referenced as a parent by any subsequent vertex. When creating a new vertex, the node attaches it to all current tips. This mechanism ensures:
Account balances are computed by traversing the entire local DAG and summing credits and debits:
balance(nodeId) = Σ genesis.amount [where genesis.from == nodeId]
+ Σ transfer.amount [where transfer.to == nodeId]
− Σ transfer.amount [where transfer.from == nodeId]
Staked amounts are tracked separately and do not reduce the spendable balance (they represent a locked commitment). Fee amounts are deducted from the sender's spendable balance at the time of transfer creation and distributed to the network treasury.
Vertices are persisted in two locations: the browser's localStorage (via the storage module) and the server-side PostgreSQL database. The PostgreSQL schema stores vertices as rows with JSONB fields for flexible structured data, enabling efficient queries by node ID, vertex type, and timestamp. On node startup, the SDK fetches all vertices involving the current node from the server to reconstruct any transactions that occurred while the node was offline.
THRA uses a Proof-of-Stake consensus model in which validators are nodes that have committed THRA tokens to the stake pool via a stake vertex. Any node with a staked balance greater than zero qualifies as a validator. The staking commitment is recorded immutably on the DAG, making it transparent and verifiable by all network participants.
In the current THRA v1.0 implementation, validator status is binary: a node either has a positive staked amount (and is a validator) or does not. Future protocol versions will implement a weighted selection algorithm where the probability of being selected as block proposer is proportional to the node's staked balance relative to total staked supply:
P(selection) = staked_amount / total_staked_supply
To become a validator, a node broadcasts a stake vertex to the network:
stake vertex is created with the staked amount, the current DAG tips as parents, and the cumulative staked total in the data field.isValidator() flag becomes true.Validator nodes participate in network governance and are eligible for a proportional share of protocol fees. The fee structure (described in Section 7) collects 0.01% of each transfer, accumulated in the protocol treasury. Future releases will distribute treasury rewards to validators pro-rata to their stake weight at a configurable epoch boundary.
THRA v2.0 will introduce slashing conditions: validators that sign conflicting vertices (double-spend attempts) will have a portion of their staked THRA burned. The slashing protocol will use cryptographic proofs of equivocation that can be submitted by any honest node, creating a permissionless fraud-proof mechanism.
THRA is the native utility token of the THRA Network. It serves three purposes: (1) a medium of exchange for peer-to-peer value transfer, (2) a staking asset for validator participation, and (3) a governance token for protocol parameter decisions in future releases.
Every newly registered node receives a genesis allocation of 50 THRA credited via a genesis vertex on first initialization. This design ensures every participant has sufficient tokens to explore the network, execute transfers, and experiment with staking without requiring a token sale or faucet request. The genesis allocation is a protocol constant and is verified by any node that receives and validates the genesis vertex.
Transfer transactions carry a network fee computed as:
fee = max(0.001, amount × 0.0001)
This represents a maximum fee rate of 0.01% with a minimum floor of 0.001 THRA. At this rate, a transfer of 100 THRA costs 0.01 THRA in fees. The fee floor prevents dust transactions (transfers of negligible value) from consuming network resources without appropriate compensation. The fee is deducted from the sender's balance at the time of vertex creation and is visible to the sender as a pre-flight preview before confirmation.
THRA does not have a fixed maximum supply in the v1.0 protocol. Each new network participant receives 50 THRA, meaning total supply grows linearly with network participation. This inflationary genesis model prioritizes network bootstrapping and broad participation over speculative scarcity. Future protocol versions may introduce a fee-burn mechanism to create deflationary pressure as transaction volume grows.
| Parameter | Value |
|---|---|
| Genesis allocation per node | 50 THRA |
| Transfer fee rate | 0.01% (0.0001) |
| Minimum transfer fee | 0.001 THRA |
| Supply model | Linear expansion per new node |
| Token decimals | 3 (minimum unit: 0.001 THRA) |
| Staking minimum | Any positive amount |
THRA forms a fully connected mesh topology among all simultaneously online nodes. Each node attempts to establish a direct RTCDataChannel connection with every other known peer. In practice, NAT traversal constraints limit the proportion of directly connected pairs, but the mesh density increases as node count grows and as peer discovery matures.
Connection establishment uses the following WebSocket signaling exchange:
{ type: "register", from: nodeId }.{ type: "peer-list", peers: string[] } listing all currently registered nodes.| Message Type | Direction | Description |
|---|---|---|
dag-vertex | Peer → Peer | Propagate a newly created DAG vertex to all connected peers |
profile-update | Peer → Peer | Broadcast an updated node profile to the network |
sync-request | Peer → Peer | Request the last 20 vertices from a peer for DAG reconciliation |
chat-message | Server → Node | Server-relayed global chat message (falls through signaling layer) |
broadcast | Node → Server → Peers | Fallback broadcast when no direct P2P channel is available |
When no direct RTCDataChannel connection is available to a peer (e.g., before ICE negotiation completes, or in restrictive NAT environments), the SDK falls back to relaying broadcast messages through the WebSocket signaling server. This ensures message delivery is never blocked by connectivity issues, at the cost of server bandwidth proportional to the broadcast payload. The fallback is automatically bypassed once a direct channel becomes available.
The SignalingClient implements automatic reconnection with a 3-second backoff: if the WebSocket connection drops, the client re-establishes it and re-registers with the signaling server. Existing RTCDataChannel connections to peers are unaffected by signaling server disconnections, as they operate independently over ICE-negotiated paths.
A complete transfer transaction follows these steps from initiation to confirmation across the network:
crypto.subtle.sign.transfer vertex is assembled with the current DAG tips as parents, embedding the signature and TX hash in the data field.POST /api/auth/dag/vertex) for inclusion in the PostgreSQL ledger mirror.Total latency from step 1 to step 7 on a modern browser is under 50ms. Peer propagation (step 8) completes within 100–300ms depending on network conditions and peer count.
The THRA SDK is structured as three TypeScript modules that can be consumed independently or as an integrated stack:
| Module | File | Description |
|---|---|---|
DecentralizedNode | src/sdk/node.ts | Primary node lifecycle, transaction, and staking APIs |
DAGLedger | src/sdk/dag.ts | Local DAG data structure, vertex management, balance computation |
SignalingClient | src/sdk/network.ts | WebSocket signaling + WebRTC P2P mesh management |
The DecentralizedNode class is the primary entry point for all THRA network interactions.
const node = new DecentralizedNode()
await node.initialize(
user: AuthUser, // { nodeId, publicKey, walletAddress, username, stakedAmount }
privateKey: string, // PKCS8 hex-encoded Ed25519 private key
token: string // JWT bearer token for server API authentication
): Promise<void>
Initializes the node: imports the key pair, loads the local DAG from storage, syncs missing vertices from the server, creates a genesis vertex if none exists, and connects to the signaling server. Must be called before any other method.
await node.transferCoin(
toNodeId: string, // Recipient node ID (64-char hex)
amount: number // Amount in THRA (minimum: fee floor)
): Promise<DagVertex>
Creates a signed transfer vertex, commits it to the local DAG, persists to server, and broadcasts to peers. Throws if balance is insufficient or amount is non-positive.
await node.stakeCoin(
amount: number // THRA to commit to validator stake pool
): Promise<DagVertex>
Creates a stake vertex committing the specified amount to the stake pool. The node becomes a validator immediately. Staked amount is reflected in node.getStakedAmount() and node.isValidator().
await node.createProfile(
displayName: string // Human-readable display name for this node
): Promise<DagVertex>
Broadcasts a profile vertex associating a display name with the node's public key and wallet address. Profile vertices are propagated to all peers, populating the network's distributed identity directory.
node.getFee(amount: number): number
// Returns: max(0.001, amount × 0.0001)
Computes the network fee for a transfer of the specified amount. Use for pre-flight cost display without committing a transaction.
node.getDagTips(): string[]
// Returns: array of current tip vertex IDs
Returns the current set of unreferenced vertices (tips) in the local DAG. Useful for applications that construct custom vertices or need to inspect DAG frontier state.
node.isValidator(): boolean
// Returns: true if node.stakedAmount > 0
node.getStakedAmount(): number
// Returns: total THRA staked by this node
node.getBalance(): number
// Returns: spendable THRA balance
node.getState(): NodeState
// Returns: { nodeId, publicKey, walletAddress, username, balance,
// stakedAmount, peerCount, profile, ledgerSize }
node.onStateChange((state: NodeState) => void): void
Registers a callback that fires whenever the node state changes (new vertex added, peer connected/disconnected, profile updated). Use this to reactively update application UI.
The DAGLedger class manages the local in-memory DAG. It is accessible via node.getDag().
await dag.addVertex(
vertex: Omit<DagVertex, 'hash'>
): Promise<DagVertex>
Adds a vertex to the DAG, computes its SHA-256 hash, updates the tip set, and fires change callbacks. Returns the complete vertex including its hash.
dag.getBalance(nodeId: string): number
dag.getTips(): string[]
dag.getAllVertices(): DagVertex[]
// Returns vertices sorted ascending by timestamp
dag.hasVertex(id: string): boolean
The SignalingClient manages WebSocket signaling and WebRTC peer connections. It is accessible via node.getNetwork().
network.broadcast(
type: string, // Message type identifier
data: Record<string, unknown> // Message payload
): void
Sends a message to all directly connected peers via RTCDataChannel. Falls back to server relay if no direct channels are available.
network.on(
type: string,
handler: (msg: Record<string, unknown>, fromPeerId?: string) => void
): void
Registers a handler for incoming messages of a given type from any peer.
network.getConnectedPeerCount(): number
The THRA SDK is distributed as TypeScript source modules and compiled to standard ES2022 JavaScript. To integrate THRA into your application, import the modules directly:
import { DecentralizedNode } from './sdk/node.js'
import { DAGLedger, DagVertex } from './sdk/dag.js'
import { SignalingClient } from './sdk/network.js'
The SDK has zero external runtime dependencies. All cryptographic operations use the browser's built-in Web Crypto API. All networking uses the browser's WebRTC and WebSocket APIs. You can add the SDK to any web project without modifying your build pipeline beyond adding the TypeScript source files.
// 1. Authenticate with the THRA server
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
})
const { user, token, privateKey } = await response.json()
// 2. Create and initialize a node
const node = new DecentralizedNode()
await node.initialize(user, privateKey, token)
// 3. Subscribe to state changes
node.onStateChange(state => {
console.log('Balance:', state.balance, 'THRA')
console.log('Peers:', state.peerCount)
console.log('Ledger size:', state.ledgerSize, 'vertices')
})
// Check balance before sending
const fee = node.getFee(10)
console.log(`Sending 10 THRA. Fee: ${fee}. Total: ${10 + fee}`)
// Execute transfer
try {
const vertex = await node.transferCoin(recipientNodeId, 10)
console.log('Transfer confirmed:', vertex.hash)
console.log('TX ID:', vertex.id)
console.log('Parents:', vertex.parentIds)
} catch (err) {
console.error('Transfer failed:', err.message)
}
// Stake 5 THRA to become a validator
const stakeVertex = await node.stakeCoin(5)
console.log('Staked successfully. Vertex:', stakeVertex.id)
console.log('Is validator:', node.isValidator()) // true
console.log('Staked amount:', node.getStakedAmount()) // 5
const network = node.getNetwork()
// Register a custom message handler
network.on('my-app-event', (msg, fromPeerId) => {
console.log('Received from', fromPeerId, ':', msg)
// Handle application-level message
})
// Broadcast a custom message to all peers
network.broadcast('my-app-event', {
type: 'my-app-event',
payload: { action: 'ping', data: 'hello network' }
})
const dag = node.getDag()
// Get all vertices
const all = dag.getAllVertices()
console.log('Total vertices:', all.length)
// Filter transfers involving this node
const myNodeId = node.getNodeId()
const myTransfers = all.filter(v =>
v.type === 'transfer' &&
(v.from === myNodeId || v.to === myNodeId)
)
// Get current DAG tips
const tips = dag.getTips()
console.log('Active tips:', tips.length)
// Compute balance for any node
const balance = dag.getBalance(someOtherNodeId)
// Profiles are propagated via P2P broadcast
// The SDK handles incoming 'profile-update' messages automatically
// Access profiles via:
const profiles = node.getAllProfiles()
profiles.forEach(p => {
console.log(p.displayName, '-', p.nodeId.substring(0, 12))
})
The THRA server exposes a REST API for account management and ledger access:
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/auth/register | POST | None | Create account. Body: {username, password}. Returns user + token. |
/api/auth/login | POST | None | Authenticate. Body: {username, password}. Returns user + token + privateKey. |
/api/auth/me | GET | Bearer JWT | Returns authenticated user object. |
/api/auth/profiles | GET | None | Returns all registered node profiles. |
/api/auth/dag/vertex | POST | Bearer JWT | Persist a DAG vertex. Body: vertex object. |
/api/auth/dag/vertices | GET | None | Fetch vertices. Query: ?nodeId=xxx to filter by node. |
/api/chat/messages | GET | None | Fetch last 12 global chat messages. |
/api/chat/messages | POST | Bearer JWT | Post a chat message. Body: {message}. |
The WebSocket endpoint at ws://host (or wss://host over TLS) accepts the following message types:
| Message | Direction | Payload |
|---|---|---|
register | Client → Server | {type, from: nodeId} |
registered | Server → Client | {type} |
peer-list | Server → Client | {type, peers: string[]} |
offer | Client → Server → Client | {type, from, to, data: RTCSdpInit} |
answer | Client → Server → Client | {type, from, to, data: RTCSdpInit} |
ice-candidate | Client → Server → Client | {type, from, to, data: RTCIceCandidateInit} |
broadcast | Client → Server → All Clients | {type, from, data: {type, ...payload}} |
THRA's security relies on the hardness of two well-studied problems:
Both assumptions are broadly accepted and underpin the security of major production systems (TLS, Bitcoin, Signal Protocol).
| Threat | Mitigation |
|---|---|
| Private key theft | Keys stored server-side as AES-GCM encrypted blobs; in-browser keys use non-extractable CryptoKey type |
| Transaction forgery | Ed25519 signature on every transfer; signature verified by recipients before acceptance |
| Double spend | DAG append-only; conflicting spends detectable via parent-chain analysis; slashing planned for v2.0 |
| Replay attack | Timestamp and unique TX hash in every vertex; duplicate IDs rejected by DAG |
| Vertex tampering | SHA-256 content hash over full vertex body; any mutation invalidates hash |
| Sybil attack | Stake-weighted consensus; validator weight proportional to staked THRA |
| Signaling server compromise | Server handles only connection brokering; cannot forge transactions; all data is verifiably signed |
| Man-in-the-middle (WS) | Production deployment uses WSS (WebSocket over TLS); ICE candidates authenticated via DTLS-SRTP |
For production deployments on THRA, application developers should:
The THRA DAG permits parallel vertex appending from multiple nodes simultaneously. In a network of N concurrently active nodes, each capable of submitting transactions at rate r, the theoretical maximum throughput is:
TPS_max = N × r (unbounded by serialization)
In practice, WebRTC data channel throughput on a modern system exceeds 100 Mbps on a local network, supporting thousands of vertex messages per second per channel. The primary bottleneck for large networks is the O(N²) mesh topology — each node maintains direct connections to all other nodes, which becomes impractical beyond ~500 simultaneous peers. THRA v2.0 will introduce a structured overlay topology (DHT-based routing) to address this.
| Phase | Typical Latency |
|---|---|
| Pre-flight validation (local) | < 1ms |
| Ed25519 signing (Web Crypto API) | 1–5ms |
| SHA-256 hashing (vertex + TX) | 0.5–2ms |
| Local DAG commit + storage | 2–10ms |
| Server persistence (REST API) | 20–100ms |
| P2P broadcast to connected peers | 50–300ms (RTT dependent) |
| Total (local confirmation) | < 20ms |
| Total (network propagation) | < 500ms |
Each DAG vertex requires approximately 400–800 bytes of JSON storage (including hash, signature, and metadata). A node performing 10 transactions per day for a year accumulates approximately 1.5 MB of local storage — well within browser localStorage quotas (typically 5–10 MB per origin). The PostgreSQL ledger mirror scales independently using standard horizontal partitioning by node ID or timestamp range.
Cold-start node initialization (first visit) completes in under 3 seconds on a typical broadband connection:
Warm-start (returning user) completes in under 1 second, as the local DAG is already populated from localStorage.
THRA's 0.01% fee rate and sub-20ms local confirmation make it well-suited for micropayment channels — tipping content creators, pay-per-request API billing, in-game economies, and real-time content monetization. Unlike payment networks that require pre-opened state channels or liquidity deposits, THRA transfers complete in a single round of cryptographic operations.
The Ed25519 node ID provides a self-sovereign identity anchor. The profile vertex type allows nodes to publish human-readable identities, credentials, and metadata without relying on a centralized directory. Applications can build DID (Decentralized Identifier) resolvers on top of the THRA profile layer.
The staking mechanism provides the foundation for yield-generating protocols. Future THRA protocol extensions will support: liquidity pools (multi-party stake vertices), atomic swaps (time-locked conditional transfer vertices), and decentralized lending (collateral-backed genesis allocations).
The custom message protocol (network.on / network.broadcast) enables applications to build real-time collaborative features entirely over the P2P mesh: multiplayer games, shared whiteboards, collaborative documents, and live event coordination — all without a central server mediating the data flow.
Since every THRA node has an Ed25519 identity, nodes can issue and verify Verifiable Credentials (W3C VC standard) directly. An educational institution running a THRA node can sign a credential vertex attesting to a user's qualification; any recipient can verify the credential by checking the issuer's public key against the THRA identity layer.
THRA Network demonstrates that a fully functional decentralized peer-to-peer network — with cryptographic identity, parallel DAG ledger, Proof-of-Stake consensus, and a native token economy — can operate entirely within the constraints of a modern web browser, requiring no external software installation. By building on the Web Crypto API for cryptographic primitives and WebRTC for peer transport, THRA inherits the security model of the browser platform while eliminating its traditional dependency on centralized application servers.
The THRA SDK provides developers with a minimal, composable API surface — fewer than 15 core methods — that covers the full lifecycle of a decentralized application: identity generation, value transfer, staking, custom message protocols, and DAG querying. The TypeScript implementation ensures type safety and IDE tooling support across the full stack.
The most meaningful measure of THRA's success is not throughput metrics or token valuation, but adoption: every browser tab that loads THRA Network and stays connected is a node that strengthens the mesh, improves transaction propagation, and contributes to a network that requires no corporation, server farm, or central authority to function. The network is its users.
THRA Network is open-source software. Contributions, protocol improvement proposals, and community governance are welcome.
THRA Network · Technical Whitepaper v1.0 · thra.network