Overview
The Walrus helper utilities provide robust functions for uploading and fetching content from Walrus storage. These utilities implement automatic fallback across multiple publisher and aggregator endpoints for reliability.
Configuration
Publisher Endpoints
TUNA uses multiple Walrus publisher endpoints with automatic fallback:
const WALRUS_PUBLISHERS = [
'https://walrus-testnet-publisher.nodes.guru/v1/blobs' ,
'https://walrus-testnet-publisher.stakely.io/v1/blobs' ,
'https://publisher.walrus-testnet.walrus.space/v1/blobs' ,
'https://walrus-testnet-publisher.everstake.one/v1/blobs' ,
'https://walrus-testnet-publisher.chainbase.online/v1/blobs' ,
'https://publisher.testnet.walrus.atalma.io/v1/blobs' ,
];
Aggregator Endpoints
const WALRUS_AGGREGATORS = [
'https://walrus-testnet-aggregator.nodes.guru/v1/blobs' ,
'https://walrus-testnet-aggregator.stakely.io/v1/blobs' ,
'https://aggregator.walrus-testnet.walrus.space/v1/blobs' ,
'https://walrus-testnet-aggregator.everstake.one/v1/blobs' ,
'https://walrus-testnet-aggregator.chainbase.online/v1/blobs' ,
'https://aggregator.testnet.walrus.atalma.io/v1/blobs' ,
];
If one endpoint fails, the function automatically tries the next one in the list.
Upload Functions
uploadToWalrus
Upload JSON content to Walrus with automatic fallback across publishers.
async function uploadToWalrus (
content : WalrusArticleContent | WalrusCommentContent
) : Promise < string >
content
WalrusArticleContent | WalrusCommentContent
required
Content object to upload (will be JSON stringified)
Returns: Promise<string> - The Walrus blob ID
Implementation Details:
Content is JSON stringified before upload
Tries each publisher endpoint sequentially until success
Adds ?epochs=30 parameter for blob retention
Handles multiple response formats from Walrus API
Throws error if all publishers fail
Response Format Handling:
const blobId =
data . newlyCreated ?. blobObject ?. blobId || // New blob
data . alreadyCertified ?. blobId || // Already exists
data . blobObject ?. blobId ; // Alternative format
Example:
import { uploadToWalrus } from '@/lib/walrus' ;
import type { WalrusArticleContent } from '@/types' ;
const content : WalrusArticleContent = {
title: 'My Article' ,
subtitle: 'An interesting story' ,
content: 'Article content...' ,
coverImage: 'blob_id_for_image' ,
};
try {
const blobId = await uploadToWalrus ( content );
console . log ( 'Uploaded to Walrus:' , blobId );
} catch ( error ) {
console . error ( 'Upload failed:' , error );
}
uploadImageToWalrus
Upload image files to Walrus storage.
async function uploadImageToWalrus ( file : File ) : Promise < string >
Image file object from file input or drag-and-drop
Returns: Promise<string> - The Walrus blob ID for the image
Implementation Details:
Converts file to ArrayBuffer for binary upload
Preserves original file MIME type
Uses same fallback logic as uploadToWalrus
Stores for 30 epochs
Example:
import { uploadImageToWalrus } from '@/lib/walrus' ;
const handleImageUpload = async ( file : File ) => {
try {
const blobId = await uploadImageToWalrus ( file );
console . log ( 'Image uploaded:' , blobId );
return blobId ;
} catch ( error ) {
console . error ( 'Image upload failed:' , error );
throw error ;
}
};
// Usage with file input
< input
type = "file"
accept = "image/*"
onChange = {(e) => {
const file = e . target . files ?.[ 0 ];
if ( file ) handleImageUpload ( file );
}}
/>
Fetch Functions
fetchFromWalrus
Fetch content from Walrus with automatic fallback across aggregators.
async function fetchFromWalrus < T = any >( blobId : string ) : Promise < T >
The Walrus blob ID to fetch
Type parameter for the expected return type
Returns: Promise<T> - The parsed JSON content
Implementation Details:
Validates blob ID format before attempting fetch
Tries each aggregator endpoint sequentially
Automatically parses JSON response
Throws error if all aggregators fail
Blob ID Validation:
// Invalid blob IDs are rejected early:
- Empty or null blob IDs
- Length < 30 characters
- Contains spaces
- Placeholder values like "blob_id"
Example:
import { fetchFromWalrus } from '@/lib/walrus' ;
import type { WalrusArticleContent } from '@/types' ;
const loadArticle = async ( blobId : string ) => {
try {
const content = await fetchFromWalrus < WalrusArticleContent >( blobId );
console . log ( 'Article:' , content . title );
return content ;
} catch ( error ) {
console . error ( 'Failed to fetch article:' , error );
throw error ;
}
};
getWalrusUrl
Get the public URL for a Walrus blob.
function getWalrusUrl ( blobId : string ) : string
Returns: string - Public URL to access the blob
Implementation:
// Uses the third aggregator (walrus.space) as default
return ` ${ WALRUS_AGGREGATORS [ 2 ] } / ${ blobId } ` ;
Example:
import { getWalrusUrl } from '@/lib/walrus' ;
const url = getWalrusUrl ( 'abc123...' );
// Returns: "https://aggregator.walrus-testnet.walrus.space/v1/blobs/abc123..."
// Use in img tags
< img src = { getWalrusUrl (article.coverImage)} alt = "Cover" />
Error Handling
All Walrus functions implement robust error handling:
Upload Error Handling
Fetch Error Handling
try {
const blobId = await uploadToWalrus ( content );
// Success
} catch ( error ) {
// Error message includes number of failed attempts
// "Walrus upload failed on all 6 publishers"
console . error ( error );
}
Type Definitions
WalrusArticleContent
type WalrusArticleContent = {
title : string ;
subtitle ?: string ;
content : string ;
coverImage ?: string ;
tags ?: string [];
};
type WalrusCommentContent = {
text ?: string ;
mediaType ?: string ;
mediaBlobId ?: string ;
};
Best Practices
Storage Duration: All uploads use epochs=30 parameter, which stores data for 30 epochs on Walrus testnet. Plan for re-upload or archival strategies for long-term storage.
Blob ID Validation: Always validate blob IDs before attempting to fetch. Invalid IDs will fail early without consuming API requests.
Error Recovery: The automatic fallback mechanism makes uploads and fetches resilient. However, you should still implement user-facing error messages for when all endpoints fail.
Source Reference
All Walrus helper functions are implemented in: