Skip to main content

Overview

TUNA is built on a dual-layer architecture that separates concerns between indexing and storage. This design enables a truly decentralized and permissionless news aggregation system.

Sui Blockchain

Provides the on-chain index via the NewsRegistry smart contract

Walrus Storage

Stores the actual article content in decentralized blob storage

Two-Layer Architecture

Layer 1: The Index (Sui Blockchain)

The NewsRegistry is a Shared Object on Sui that maintains a vector (array) of blob IDs. Think of it as a decentralized pointer system:
  • Registry Object ID: 0x68c01d2c08923d5257a5a9959d7c9250c4053dbe4641e229ccff2f35e6a3bb6d
  • Package ID: 0xadf0a6ce11dd75d3d44930ab5bf55781801dea2bfead056eb0bb59c1aa1e9e66
  • Module: news_registry
Reading from the registry is free and permissionless - no wallet or SUI tokens required!

Layer 2: The Content (Walrus)

All article JSON data is stored as immutable blobs on the Walrus decentralized storage network:
interface WalrusArticleContent {
  title: string;
  content: string;          // HTML string
  summary?: string;
  source: string;           // e.g., "twitter", "rss", "onchain"
  url?: string;             // Original link
  image?: string;           // Cover image URL
  author?: string;
  timestamp: number;
}

Data Flow

Here’s how applications fetch news from TUNA:
1

Query Sui Registry

Fetch the NewsRegistry object to get the list of blob IDs
const registry = await suiClient.getObject({
  id: REGISTRY_ID,
  options: { showContent: true }
});

const blobIds = registry.data.content.fields.latest_blobs;
2

Extract Blob IDs

The latest_blobs field contains an array of Walrus blob IDs, ordered chronologically
// Get most recent 20 articles (newest first)
const recentBlobIds = blobIds.slice(-20).reverse();
3

Fetch from Walrus

Retrieve actual article JSON from Walrus aggregators
const article = await fetch(
  `https://aggregator.walrus-testnet.walrus.space/v1/${blobId}`
);
const data = await article.json();

Component Architecture

The TUNA frontend follows a modular React architecture:

Configuration Layer

// src/config/index.ts
export const CONTRACT_CONFIG = {
  PACKAGE_ID: '0xadf0a6ce11dd75d3d44930ab5bf55781801dea2bfead056eb0bb59c1aa1e9e66',
  REGISTRY_ID: '0x68c01d2c08923d5257a5a9959d7c9250c4053dbe4641e229ccff2f35e6a3bb6d',
  MODULE_NAME: 'news_registry',
};

export const WALRUS_CONFIG = {
  PUBLISHER_URL: 'https://publisher.walrus-testnet.walrus.space/v1/store',
  AGGREGATOR_URL: 'https://aggregator.walrus-testnet.walrus.space/v1',
};

Core Libraries

Provides functions to create Sui transactions for:
  • Tipping articles: createTipArticleTransaction()
  • Posting comments: createPostCommentTransaction()
  • Posting comments with media: createPostCommentWithBlobTransaction()
  • Tipping comments: createTipCommentTransaction()
All transactions use the @mysten/sui Transaction builder pattern.
Handles all Walrus interactions with fallback logic:
  • uploadToWalrus() - Upload content with 6 publisher endpoints
  • fetchFromWalrus() - Fetch content with 6 aggregator endpoints
  • uploadImageToWalrus() - Upload binary image files
  • getWalrusUrl() - Generate public blob URLs

Data Hooks

// src/hooks/useNews.ts
export function useLatestNews(limit: number = 100) {
  return useQuery({
    queryKey: ['latestNews', limit],
    queryFn: async () => {
      // 1. Fetch registry from Sui
      const registry = await suiClient.getObject({...});
      
      // 2. Extract blob IDs
      const blobIds = fields.latest_blobs.slice(-limit).reverse();
      
      // 3. Fetch articles from Walrus in parallel
      const articles = await Promise.all(
        blobIds.map(async (blobId) => {
          const content = await fetchFromWalrus(blobId);
          const engagement = await getArticleEngagement(blobId);
          return { ...content, ...engagement };
        })
      );
      
      return articles;
    },
  });
}

Why This Architecture?

Scalability

Sui only stores lightweight pointers, not full content. Storage scales horizontally on Walrus.

Cost Efficiency

Walrus storage is significantly cheaper than storing full articles on-chain.

Immutability

Once published, articles are permanent and censorship-resistant on both layers.

Permissionless

Anyone can read the registry and fetch content without permissions or gas fees.

Network Configuration

TUNA currently runs on Sui Testnet and Walrus Testnet:
export const NETWORK_CONFIG = {
  NETWORK: 'testnet',
  RPC_URL: 'https://fullnode.testnet.sui.io:443',
};
This is a testnet deployment. For production use, deploy to Sui Mainnet and Walrus Mainnet with updated contract addresses.

Integration Approach

Developers can integrate TUNA in two ways:
  1. Direct Integration: Use the configuration and libraries to query the registry directly
  2. Package Installation: Import TUNA as a dependency and use the pre-built hooks
Both approaches are permissionless and require no special access - just the Registry Object ID.

Next Steps

Sui Integration

Learn how transactions work on Sui

Walrus Storage

Deep dive into Walrus storage

NewsRegistry Contract

Understand the smart contract

Integration Guide

Start building with TUNA

Build docs developers (and LLMs) love