Skip to content

Conversation

@Jitmisra
Copy link

@Jitmisra Jitmisra commented Dec 13, 2025

Fixes #25 -

Changes:

  • Added new StorageService with Web3.Storage as primary provider
  • Web3.Storage offers 5GB free storage with no cost restrictions
  • Maintains backward compatibility with existing Pinata setup
  • Falls back to Pinata if Web3.Storage is not configured
  • Added multi-gateway fallback for image loading reliability
  • Updated all files using IPFS upload functionality

New Environment Variable:

Benefits:

  • Free 5GB storage (vs Pinata's limited free tier)
  • Same IPFS hash format (content-addressable)
  • Backed by Filecoin for persistence
  • Multiple gateway fallbacks for reliability

Summary by CodeRabbit

  • New Features

    • Added multi-provider support for file uploads with automatic fallback to ensure upload resilience.
    • Implemented alternative gateway fallback for image loading to improve reliability.
  • Chores

    • Refactored storage service architecture for improved maintainability.
    • Updated environment configuration to support additional storage providers.

✏️ Tip: You can customize this high-level summary in your review settings.

Fixes StabilityNexus#25 - Find an alternative to IPFS

## Changes:
- Added new StorageService with Web3.Storage as primary provider
- Web3.Storage offers 5GB free storage with no cost restrictions
- Maintains backward compatibility with existing Pinata setup
- Falls back to Pinata if Web3.Storage is not configured
- Added multi-gateway fallback for image loading reliability
- Updated all files using IPFS upload functionality

## New Environment Variable:
- WEB3_STORAGE_TOKEN: Get free at https://web3.storage

## Benefits:
- Free 5GB storage (vs Pinata's limited free tier)
- Same IPFS hash format (content-addressable)
- Backed by Filecoin for persistence
- Multiple gateway fallbacks for reliability
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Walkthrough

The PR replaces Pinata-only IPFS uploads with a new multi-provider storage service that prioritizes Web3.Storage (free pinning) with Pinata as a fallback. Imports across the codebase are migrated, and gateway fallback logic in image widgets is enhanced to support multiple alternative IPFS gateways.

Changes

Cohort / File(s) Summary
Configuration
.env.stencil
Added WEB3_STORAGE_TOKEN environment variable with documentation for Web3.Storage free IPFS pinning. Retained existing Pinata and Alchemy keys.
Service Layer Replacement
lib/utils/services/ipfs_services.dart, lib/utils/services/storage_service.dart
Removed single-provider Pinata upload service. Introduced new StorageService class with multi-provider support: Web3.Storage as primary (free), Pinata as fallback. Includes CID extraction and alternative gateway generation utilities. Backward-compatible uploadToIPFS wrapper function provided.
Page Imports
lib/pages/mint_nft/mint_nft_images.dart, lib/pages/organisations_pages/create_organisation.dart, lib/pages/register_user_page.dart, lib/pages/tree_details_page.dart
Updated imports from ipfs_services.dart to storage_service.dart; no logic changes.
Widget Gateway Fallback Logic
lib/widgets/profile_widgets/profile_section_widget.dart, lib/widgets/profile_widgets/user_profile_viewer_widget.dart
Added storage_service.dart import. Replaced hardcoded single fallback gateway logic with dynamic alternative gateway retrieval via StorageService.getAlternativeGateways(), enabling fallback to secondary gateways on image load error.

Sequence Diagram

sequenceDiagram
    participant UI as UI Layer
    participant SS as StorageService
    participant W3S as Web3.Storage API
    participant PIN as Pinata API
    participant IPFS as IPFS Gateways

    UI->>SS: uploadFile(file, setUploadingState)
    activate SS
    SS->>SS: setUploadingState(true)
    
    rect rgb(76, 175, 80, 0.1)
    note over SS,W3S: Primary: Web3.Storage
    SS->>W3S: POST /upload (multipart)
    alt Web3.Storage Success
        W3S-->>SS: w3s.link gateway URL
        SS->>IPFS: return gateway URL
    else Web3.Storage Fails
        W3S-->>SS: error
        rect rgb(255, 193, 7, 0.1)
        note over SS,PIN: Fallback: Pinata
        SS->>PIN: POST /pinning/pinFileToIPFS
        alt Pinata Success
            PIN-->>SS: gateway URL
            SS->>IPFS: return gateway URL
        else Pinata Fails
            PIN-->>SS: error
            SS->>SS: log error
            SS-->>UI: null
        end
        end
    end
    end
    
    SS->>SS: setUploadingState(false)
    SS-->>UI: gateway URL or null
    deactivate SS
    
    UI->>SS: getAlternativeGateways(originalUrl)
    activate SS
    SS->>SS: extractCidFromUrl(url)
    SS-->>UI: List[alternative gateway URLs]
    deactivate SS
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Primary complexity areas:
    • New StorageService class with multi-provider upload logic, environment variable handling, and fallback mechanism (~150 lines of logic)
    • CID extraction and alternative gateway generation utilities
    • Error handling and state management across provider transitions
  • Mitigation factors:
    • Import migrations are mechanical and repetitive across multiple files (low friction)
    • Widget changes follow a clear, consistent pattern (straightforward improvement)
    • Well-structured separation of concerns between service and UI layers

Poem

🐰 A rabbit's den now stores with grace,
Web3 and Pinata share the space,
When gateways fail, alternatives bloom,
No costly IPFS in this room!
Free pinning hops through multiple doors,
Our decentralized dreams now soar! 🌐

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing Pinata with Web3.Storage as the primary IPFS provider, which is the core objective of this PR.
Linked Issues check ✅ Passed The PR successfully implements Web3.Storage as a cost-free IPFS alternative [#25], maintains backward compatibility with Pinata as fallback, and preserves on-chain hash storage without cost restrictions.
Out of Scope Changes check ✅ Passed All changes directly support the primary objective of replacing Pinata with Web3.Storage; updates to environment variables, service implementations, import statements, and gateway fallback logic are all within scope of the feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jitmisra
Copy link
Author

tean name bigbull

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
lib/widgets/profile_widgets/user_profile_viewer_widget.dart (1)

168-186: Gateway fallback only tries one alternative.

The fallback logic uses alternatives[1] (ipfs.io) but doesn't attempt the remaining gateways (Cloudflare, dweb.link) if that also fails. Consider iterating through more alternatives for improved reliability, or accept this as a reasonable tradeoff to avoid deeply nested error handlers.

A more comprehensive fallback could use a recursive or loop-based approach:

Widget _buildImageWithFallback(String originalUrl, int gatewayIndex) {
  final alternatives = StorageService.getAlternativeGateways(originalUrl);
  if (gatewayIndex >= alternatives.length) {
    return Icon(Icons.person, size: 40, color: getThemeColors(context)['textSecondary']);
  }
  return Image.network(
    alternatives[gatewayIndex],
    fit: BoxFit.cover,
    errorBuilder: (context, error, stackTrace) {
      return _buildImageWithFallback(originalUrl, gatewayIndex + 1);
    },
  );
}
lib/utils/services/storage_service.dart (1)

68-98: Consider adding HTTP request timeouts.

The HTTP requests to Web3.Storage (and Pinata) don't specify timeouts. On slow or unresponsive networks, this could cause the upload to hang indefinitely, blocking the UI.

 static Future<String?> _uploadToWeb3Storage(File file) async {
   try {
     final url = Uri.parse('https://api.web3.storage/upload');
     
     final request = http.MultipartRequest('POST', url);
     request.headers.addAll({
       'Authorization': 'Bearer $_web3StorageToken',
     });

     request.files.add(
       await http.MultipartFile.fromPath('file', file.path),
     );

-    final streamedResponse = await request.send();
+    final streamedResponse = await request.send().timeout(
+      const Duration(minutes: 2),
+      onTimeout: () {
+        throw TimeoutException('Web3.Storage upload timed out');
+      },
+    );
     final response = await http.Response.fromStream(streamedResponse);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02cb1fd and ae5b2ad.

📒 Files selected for processing (9)
  • .env.stencil (1 hunks)
  • lib/pages/mint_nft/mint_nft_images.dart (1 hunks)
  • lib/pages/organisations_pages/create_organisation.dart (1 hunks)
  • lib/pages/register_user_page.dart (1 hunks)
  • lib/pages/tree_details_page.dart (1 hunks)
  • lib/utils/services/ipfs_services.dart (0 hunks)
  • lib/utils/services/storage_service.dart (1 hunks)
  • lib/widgets/profile_widgets/profile_section_widget.dart (2 hunks)
  • lib/widgets/profile_widgets/user_profile_viewer_widget.dart (2 hunks)
💤 Files with no reviewable changes (1)
  • lib/utils/services/ipfs_services.dart
🔇 Additional comments (12)
.env.stencil (1)

3-9: Well-documented environment configuration.

The new WEB3_STORAGE_TOKEN variable is properly documented with helpful comments indicating where to obtain the token and the benefits (5GB free). The distinction between the recommended provider (Web3.Storage) and legacy fallback (Pinata) is clear.

lib/pages/register_user_page.dart (1)

10-10: Import migration looks correct.

The import change to storage_service.dart is appropriate. The uploadToIPFS function continues to work via the backward-compatible wrapper in the new service.

lib/pages/tree_details_page.dart (1)

11-11: Import migration is correct.

The import change aligns with the new storage service architecture while maintaining backward compatibility through the uploadToIPFS wrapper function.

lib/pages/mint_nft/mint_nft_images.dart (1)

10-10: Import updated correctly.

The migration to storage_service.dart maintains the existing upload flow for multiple NFT images.

lib/pages/organisations_pages/create_organisation.dart (1)

9-9: Import migration completed.

The storage service import correctly replaces the legacy IPFS service for organisation logo uploads.

lib/widgets/profile_widgets/user_profile_viewer_widget.dart (1)

9-9: Import added for gateway fallback support.

The storage service import enables the new multi-gateway fallback functionality.

lib/widgets/profile_widgets/profile_section_widget.dart (2)

10-10: Storage service import added.

Enables the gateway fallback functionality for profile photo loading.


391-415: Consistent gateway fallback implementation.

The fallback pattern matches user_profile_viewer_widget.dart, maintaining consistency across the codebase. The same single-alternative limitation applies here.

lib/utils/services/storage_service.dart (4)

1-15: Well-structured storage service with clear documentation.

The service design with Web3.Storage as the primary free provider and Pinata as fallback aligns well with the PR objectives. The class documentation clearly explains the benefits of Web3.Storage.


145-157: Good selection of fallback gateways.

The gateway list provides solid redundancy with well-known, reliable IPFS gateways. The w3s.link gateway (Web3.Storage's own) is appropriately placed first for best performance with Web3.Storage uploads.


160-167: Clean backward compatibility wrapper.

The uploadToIPFS function maintains API compatibility with existing code, making the migration seamless across the codebase.


133-143: CID regex suggestion is factually incorrect.

The regex [a-zA-Z0-9]+ is overly permissive (includes 0, O, I, l which are invalid in Base58), but it will match all valid CIDs in practice since real CIDv0 and CIDv1 identifiers contain only a subset of alphanumeric characters.

The suggested improvement—adding underscore and hyphen [a-zA-Z0-9_-]—is wrong. Neither underscore nor hyphen appear in IPFS CID specifications: CIDv0 uses Base58 (alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz), and CIDv1 typically uses RFC-4648 Base32 (alphabet: a-z2-7). Neither includes _ or -. The current regex, while not ideally strict, is functionally sufficient and the suggested modification would introduce invalid characters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant