walrus 0.1.0 copy "walrus: ^0.1.0" to clipboard
walrus: ^0.1.0 copied to clipboard

Flutter SDK for Walrus decentralized storage protocol built on Sui blockchain.

Walrus Flutter SDK #

Pub Version License: MIT Flutter

A Flutter SDK for Walrus, the decentralized storage protocol built on Sui blockchain.

Note: This is a community-maintained SDK. For official SDKs, see Walrus Documentation.

Features #

  • Store - Upload blobs to the Walrus network
  • Read - Retrieve blobs by their ID
  • Encryption - Client-side AES-GCM encryption support
  • Streaming - Handle large files with streaming upload/download
  • Async/Await - Modern Dart async patterns
  • Flutter Ready - Works seamlessly with Flutter mobile apps

Installation #

Add walrus to your pubspec.yaml:

dependencies:
  walrus: ^0.0.1

Then run:

flutter pub get

🚀 Quick Start #

Initialization #

Initialize once in your app's main.dart:

import 'package:flutter/material.dart';
import 'package:walrus/walrus.dart';

Future<void> main() async {
  await WalrusClient.initialize(
    publisherUrl: 'https://publisher.walrus-testnet.walrus.space',
    aggregatorUrl: 'https://aggregator.walrus-testnet.walrus.space',
  );
  
  runApp(MyApp());
}

Basic Usage #

After initialization, use the singleton instance anywhere:

import 'dart:convert';
import 'dart:typed_data';
import 'package:walrus/walrus.dart';

// Get singleton instance
final walrus = WalrusClient.instance;

// Upload data
final data = Uint8List.fromList(utf8.encode('Hello, Walrus!'));
final result = await walrus.store(data);

print('Blob ID: ${result.blobId}');
print('Object ID: ${result.objectId}');
print('Is New: ${result.isNew}');
print('URL: ${walrus.getBlobUrl(result.blobId)}');

// Download data
final retrieved = await walrus.read(result.blobId);
print('Content: ${utf8.decode(retrieved)}');

Upload with Options #

import 'dart:io';
import 'package:walrus/walrus.dart';

final walrus = WalrusClient.instance;

// Read image file
final imageBytes = await File('photo.jpg').readAsBytes();

// Upload with options
final result = await walrus.store(
  imageBytes,
  epochs: 5,           // Storage duration (5 epochs)
  permanent: true,     // Cannot be deleted
  // deletable: true,  // Can be deleted by owner
);

print('Image URL: ${walrus.getBlobUrl(result.blobId)}');

Important: Up to (including) Walrus version 1.32, blobs are stored as permanent by default. Starting with version 1.33, newly stored blobs are deletable by default. If you care about blob persistence, make sure to use the appropriate flag.

Mainnet Configuration #

Future<void> main() async {
  await WalrusClient.initialize(
    publisherUrl: 'https://your-mainnet-publisher.com', // Auth required
    aggregatorUrl: 'https://aggregator.walrus-mainnet.walrus.space',
  );
  
  runApp(MyApp());
}

📖 API Reference #

WalrusClient #

Static Methods

Method Description
initialize({required String publisherUrl, required String aggregatorUrl, Dio? dio}) Initialize singleton instance
instance Get singleton instance (throws if not initialized)
isInitialized Check if initialized
reset() Reset singleton (for testing)

Instance Methods

Method Description Returns
store(Uint8List data, {int? epochs, bool? deletable, bool? permanent}) Upload blob to network Future<StoreResponse>
storeFile(String path, {int? epochs, bool? deletable, bool? permanent}) Upload file by path Future<StoreResponse>
read(String blobId) Download blob by ID Future<Uint8List>
getBlobUrl(String blobId) Get HTTP URL for blob String
exists(String blobId) Check if blob exists Future<bool>

StoreResponse #

class StoreResponse {
  final String blobId;      // Unique blob identifier
  final String? objectId;   // Sui Object ID
  final int? endEpoch;      // Storage expiration epoch
  final bool isNew;         // True if newly created, false if already existed
  final String? mediaType;  // Media type of the blob
}

Exceptions #

// Base exception
class WalrusException implements Exception {
  final String message;
  final int? statusCode;
  final Object? cause;
}

// Blob not found
class BlobNotFoundException extends WalrusException { }

// Store operation failed
class StoreException extends WalrusException { }

// Network request failed
class NetworkException extends WalrusException { }

🔧 Flutter Integration #

Display Walrus Images #

import 'package:cached_network_image/cached_network_image.dart';
import 'package:walrus/walrus.dart';

class WalrusImage extends StatelessWidget {
  final String blobId;

  const WalrusImage({required this.blobId});

  @override
  Widget build(BuildContext context) {
    final walrus = WalrusClient.instance;
    
    return CachedNetworkImage(
      imageUrl: walrus.getBlobUrl(blobId),
      placeholder: (context, url) => CircularProgressIndicator(),
      errorWidget: (context, url, error) => Icon(Icons.error),
    );
  }
}

Upload from Camera/Gallery #

import 'package:image_picker/image_picker.dart';
import 'package:walrus/walrus.dart';

Future<String?> uploadImage() async {
  final picker = ImagePicker();
  final image = await picker.pickImage(source: ImageSource.gallery);
  
  if (image == null) return null;
  
  final bytes = await image.readAsBytes();
  final walrus = WalrusClient.instance;
  final result = await walrus.store(bytes, permanent: true);
  
  return result.blobId;
}

🌐 Network Endpoints #

Network Publisher Aggregator
Testnet https://publisher.walrus-testnet.walrus.space https://aggregator.walrus-testnet.walrus.space
Mainnet (Auth required - No public publisher) https://aggregator.walrus-mainnet.walrus.space

Note: On Mainnet, there are no public publishers without authentication, as they consume both SUI and WAL tokens. You need to run your own publisher node or use an authenticated service.

🛡️ Error Handling #

import 'package:walrus/walrus.dart';

try {
  final walrus = WalrusClient.instance;
  final result = await walrus.store(data);
  print('Stored: ${result.blobId}');
} on StateError catch (e) {
  print('Not initialized: ${e.message}');
} on BlobNotFoundException catch (e) {
  print('Blob not found: ${e.message}');
} on StoreException catch (e) {
  print('Store failed: ${e.message}');
} on NetworkException catch (e) {
  print('Network error: ${e.message}');
} on WalrusException catch (e) {
  print('Walrus error: ${e.message}');
}

🗺️ Roadmap #

  • ✅ Basic store/read operations
  • ✅ Deletable/Permanent blob support
  • ❌ AES-GCM encryption
  • ❌ Streaming upload/download for large files
  • ❌ Sui blockchain integration (Object management)
  • ❌ Multi-publisher support
  • ❌ Retry with exponential backoff

🤝 Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create an issue (main)
  3. Create your feature branch (git checkout -b feature/feature-name)
  4. Commit your changes (git commit -m 'Add some feature')
  5. Push to the branch (git push origin feature/feature-name)
  6. Open a Pull Request

Development Setup #

# Clone the repository
git clone https://github.com/keem-hyun/walrus_dart.git
cd walrus

# Get dependencies
flutter pub get

# Run tests
flutter test

# Check formatting
dart format --set-exit-if-changed .

# Analyze code
dart analyze

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

💬 Support #

  • 📫 Open an issue for bug reports
  • 💡 Start a discussion for feature requests
  • ⭐ Star this repo if you find it useful!

0
likes
150
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for Walrus decentralized storage protocol built on Sui blockchain.

Repository (GitHub)
View/report issues

Topics

#walrus #sui #blockchain #decentralized-storage #web3

Documentation

API reference

License

MIT (license)

Dependencies

dio, flutter

More

Packages that depend on walrus