skills/storage/download-file/SKILL.md
# Download File from 0G Storage ## Metadata - **Category**: storage - **SDK**: `@0glabs/0g-ts-sdk` ^0.3.3, `ethers` ^6.13.0 - **Activation Triggers**: "download file", "retrieve from 0G", "get file", "fetch from storage" ## Purpose Download and verify files from 0G decentralized storage using a root hash. Supports verified downloads with Merkle proof validation to ensure data integrity. ## Prerequisites - Node.js >= 18 - `@0glabs/0g-ts-sdk` installed - Root hash of the file to download - `
npx skillsauth add 0gfoundation/0g-agent-skills skills/storage/download-fileInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
@0glabs/0g-ts-sdk ^0.3.3, ethers ^6.13.0Download and verify files from 0G decentralized storage using a root hash. Supports verified downloads with Merkle proof validation to ensure data integrity.
@0glabs/0g-ts-sdk installed.env with STORAGE_INDEXERIndexer instanceindexer.download() with the root hash, output path, and verified flagtrue)import { Indexer } from '@0glabs/0g-ts-sdk';
import 'dotenv/config';
async function downloadFile(rootHash: string, outputPath: string): Promise<void> {
const indexer = new Indexer(process.env.STORAGE_INDEXER!);
// Download with Merkle verification (recommended)
// Note: download() can throw errors (e.g., JsonRpcError) in addition to returning them
try {
const err = await indexer.download(rootHash, outputPath, true);
if (err) throw err;
} catch (error: any) {
throw new Error(`Download failed: ${error.message}`);
}
console.log(`Downloaded to ${outputPath}`);
}
// Usage
await downloadFile('0xabc123...', './downloads/my-file.pdf');
import { Indexer } from '@0glabs/0g-ts-sdk';
import * as fs from 'fs';
import * as path from 'path';
import 'dotenv/config';
async function downloadWithValidation(rootHash: string, outputPath: string): Promise<void> {
if (!process.env.STORAGE_INDEXER) {
throw new Error('STORAGE_INDEXER not set in .env');
}
// Validate root hash format
if (!rootHash.startsWith('0x') || rootHash.length < 10) {
throw new Error('Invalid root hash format');
}
// Ensure output directory exists
const dir = path.dirname(outputPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const indexer = new Indexer(process.env.STORAGE_INDEXER!);
try {
// download() can throw OR return an error — handle both
const err = await indexer.download(rootHash, outputPath, true);
if (err) throw err;
console.log(`Downloaded and verified: ${outputPath}`);
const stats = fs.statSync(outputPath);
console.log(`File size: ${stats.size} bytes`);
} catch (error: any) {
if (error.message?.includes('not found') || error.message?.includes('JsonRpc')) {
throw new Error(`File not found for root hash: ${rootHash}`);
}
throw error;
}
}
async function downloadBatch(
files: Array<{ rootHash: string; outputPath: string }>,
): Promise<void> {
const indexer = new Indexer(process.env.STORAGE_INDEXER!);
const results = await Promise.allSettled(
files.map(async ({ rootHash, outputPath }) => {
const err = await indexer.download(rootHash, outputPath, true);
if (err) throw err;
}),
);
results.forEach((result, i) => {
if (result.status === 'fulfilled') {
console.log(`Downloaded: ${files[i].outputPath}`);
} else {
console.error(`Failed: ${files[i].rootHash} — ${result.reason}`);
}
});
}
// BAD: Unverified download in production
await indexer.download(rootHash, outputPath, false);
// BAD: No error handling — download() can THROW in addition to returning errors
await indexer.download(rootHash, outputPath, true);
// If file doesn't exist, throws JsonRpcError!
// GOOD: Proper error handling
try {
const err = await indexer.download(rootHash, outputPath, true);
if (err) throw err;
} catch (error) {
console.error('Download failed:', error);
}
// BAD: Downloading to non-existent directory
await indexer.download(rootHash, '/nonexistent/path/file.txt', true);
| Error | Cause | Fix |
| ----------------------- | --------------------------------- | ------------------------------------ |
| file not found | Invalid or non-existent root hash | Verify the root hash is correct |
| verification failed | Data integrity check failed | Re-download or report issue |
| ENOENT | Output directory doesn't exist | Create directory with fs.mkdirSync |
| EACCES | No write permission | Check file system permissions |
| indexer not available | Wrong indexer URL | Check STORAGE_INDEXER in .env |
development
# Upload File to 0G Storage ## Metadata - **Category**: storage - **SDK**: `@0glabs/0g-ts-sdk` ^0.3.3, `ethers` ^6.13.0 - **Activation Triggers**: "upload file", "store on 0G", "ZgFile", "save to storage" ## Purpose Upload files to 0G decentralized storage using the ZgFile API and Indexer. Files are split into chunks, organized as a Merkle tree, and distributed across storage nodes. Returns a root hash for later retrieval. ## Prerequisites - Node.js >= 18 - `@0glabs/0g-ts-sdk` and `ethers`
development
# Merkle Verification ## Metadata - **Category**: storage - **SDK**: `@0glabs/0g-ts-sdk` ^0.3.3 - **Activation Triggers**: "verify file", "merkle proof", "data integrity", "root hash", "check file" ## Purpose Compute root hashes and verify data integrity for files stored on 0G Storage. Uses Merkle tree proofs to cryptographically verify that downloaded data matches what was originally uploaded. ## Prerequisites - Node.js >= 18 - `@0glabs/0g-ts-sdk` installed ## Quick Workflow 1. Create
development
# Storage + Chain Integration ## Metadata - **Category**: cross-layer - **SDK**: `@0glabs/0g-ts-sdk` ^0.3.3, `ethers` ^6.13.0 - **Activation Triggers**: "on-chain reference", "NFT metadata on 0G", "store hash on-chain", "registry contract", "chain and storage" ## Purpose Combine 0G Storage with 0G Chain smart contracts to create on-chain references to off-chain data. Common patterns include NFT metadata storage, content registries, and verifiable document systems. ## Prerequisites - Node
development
# Compute + Storage Integration ## Metadata - **Category**: cross-layer - **SDK**: `@0glabs/0g-serving-broker` ^0.6.5, `@0glabs/0g-ts-sdk` ^0.3.3, `ethers` ^6.13.0 - **Activation Triggers**: "AI with storage", "generate and store", "transcribe and store", "inference with storage", "AI pipeline" ## Purpose Combine 0G Compute (AI inference) with 0G Storage for end-to-end AI pipelines: generate content with AI and persist results to decentralized storage, or load data from storage and process