A Git-like version control system built on Sui blockchain for metadata and Walrus for decentralized file storage.
- Decentralized Storage: Files stored on Walrus (chain-agnostic blob storage)
- Blockchain Metadata: Version history and DAG structure on Sui
- Git-like Operations: commit, branch, checkout, log, diff
- No Token Required: Free uploads up to 10MB on Walrus testnet
- Immutable History: Tamper-proof commit history
- Multi-branch Support: Create and manage multiple branches
βββββββββββββββββββββββββββββββββββββββββββ
β VersionFS Client β
β (TypeScript/Node.js Application) β
βββββββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββ΄ββββββββββ
β β
βββββββββΌβββββββββ ββββββββΌβββββββββ
β Sui Blockchainβ β Walrus β
β (Metadata) β β (File Data) β
β β β β
β - Repositories β β - Blob IDs β
β - Commits β β - File Data β
β - Branches β β - Directory β
β - DAG Structureβ β Trees β
ββββββββββββββββββ βββββββββββββββββ
- Node.js >= 18.0.0
- Sui CLI (for deployment)
- A Sui testnet wallet with some testnet SUI
# Clone the repository
git clone <your-repo>
cd versionfs
# Install dependencies
npm install
# Create .env file
cp .env.example .env
# Edit .env with your private key
nano .env# Build the Move package
sui move build
# Deploy to testnet
sui client publish --gas-budget 100000000
# Note the Package ID from the output
# Update PACKAGE_ID in your codeimport VersionFSClient from './versionFSClient';
const PRIVATE_KEY = "your_sui_private_key";
const PACKAGE_ID = "your_deployed_package_id";
const client = new VersionFSClient(PRIVATE_KEY, 'testnet', PACKAGE_ID);
// Initialize repository
const repoId = await client.init("my-project");
console.log(`Repository created: ${repoId}`);// Create some files
const files = [
{
path: 'README.md',
data: '# My Project\n\nDecentralized and awesome!'
},
{
path: 'src/main.ts',
data: 'console.log("Hello Walrus!");'
}
];
// Commit to main branch
const versionId = await client.commit(
files,
'Initial commit',
'main'
);
console.log(`Commit created: ${versionId}`);// View last 10 commits
await client.log('main', 10);// Create feature branch
await client.createBranch('feature/new-api');
// Make changes on the branch
const newFiles = [
{
path: 'src/api.ts',
data: 'export class API { /* ... */ }'
}
];
await client.commit(newFiles, 'Add API module', 'feature/new-api');// Checkout specific commit
await client.checkout(versionId, './output-dir');
// Or checkout a branch
await client.checkout('main', './main-branch');new VersionFSClient(
privateKey: string,
network: 'testnet' | 'mainnet',
packageId?: string
)Initialize a new repository.
Create a new commit with files.
await client.commit(
[{ path: 'file.txt', data: 'content' }],
'Commit message',
'main'
);Create a new branch.
Checkout files from a commit or branch.
View commit history.
Get file content at specific version.
Compare two versions.
View repository status.
Upload file to Walrus.
const walrus = new WalrusService();
const blobId = await walrus.uploadFile('Hello World', 3);Download file from Walrus.
const data = await walrus.downloadFile(blobId);
const text = new TextDecoder().decode(data);Upload directory structure as JSON.
Download and parse directory structure.
Create repository on Sui blockchain.
Create commit transaction.
Create branch transaction.
Get repository information.
Get current branch head.
Get version details.
# Initialize repository
npm run init
# Create commit
npm run commit <repo-id> <cap-id>
# View history
npm run log <repo-id> <cap-id>
# View status
npm run status <repo-id> <cap-id>
# Run complete workflow
npm run example workflow
# Test Walrus directly
npm run test:walrusversionfs/
βββ sources/
β βββ version_fs.move # Sui Move smart contract
βββ src/
β βββ services/
β β βββ walrusService.ts # Walrus storage operations
β β βββ suiService.ts # Sui blockchain operations
β βββ versionFSClient.ts # High-level client API
β βββ example.ts # Usage examples
βββ Move.toml # Move package config
βββ package.json # Node.js config
βββ tsconfig.json # TypeScript config
βββ README.md # This file
Create a .env file:
# Sui Configuration
SUI_PRIVATE_KEY=suiprivkey1...
SUI_NETWORK=testnet
PACKAGE_ID=0x...
# Walrus Configuration (optional, uses defaults)
WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space- Free uploads: Up to 10 MB per file
- No WAL tokens required: Public publishers available
- Storage duration: Specified in epochs (1 epoch β 1 day on testnet)
# Upload file via curl
curl -X PUT \
"https://publisher.walrus-testnet.walrus.space/v1/blobs?epochs=3" \
--upload-file myfile.txt
# Download file
curl "https://aggregator.walrus-testnet.walrus.space/v1/blobs/<blob-id>"const walrus = new WalrusService();
// Upload
const blobId = await walrus.uploadFile(fileData, 3);
// Download
const data = await walrus.downloadFile(blobId);
// Check existence
const exists = await walrus.blobExists(blobId);The version_fs.move contract manages:
- Repositories: Owned objects with metadata
- Version Nodes: DAG structure for commits
- Branches: Pointers to version heads
- Capabilities: Access control via RepoCap
struct Repository {
id: UID,
name: String,
owner: address,
branches: VecMap<String, ID>,
versions: Table<ID, VersionNode>,
version_count: u64,
}
struct VersionNode {
root_blob_id: String, // Walrus blob ID
parents: vector<ID>, // Parent commits
author: address,
timestamp: u64,
message: String,
version_id: ID,
}RepositoryCreatedNewCommitBranchUpdatedBranchCreated
- Private Key Safety: Never commit private keys to version control
- Capability Objects: Store RepoCap safely - it proves ownership
- Immutable History: Once committed, data cannot be deleted
- Public Testnet: Don't store sensitive data on testnet
# Test Walrus upload/download
npm run test:walrus
# Test Sui interactions
npm run test:sui
# Run all examples
npm run example workflow// 1. Initialize
const client = new VersionFSClient(PRIVATE_KEY, 'testnet', PACKAGE_ID);
const repoId = await client.init("my-project");
const capId = "..."; // From transaction output
client.setRepoIds(repoId, capId);
// 2. First commit
await client.commit([
{ path: 'README.md', data: '# Hello' }
], 'Initial commit');
// 3. Create feature branch
await client.createBranch('feature/auth');
// 4. Work on feature
await client.commit([
{ path: 'auth.ts', data: 'export class Auth {}' }
], 'Add authentication', 'feature/auth');
// 5. View history
await client.log('feature/auth');
// 6. Checkout
await client.checkout('main', './main-code');You need testnet SUI for gas fees. Get it from:
- Deploy the contract first:
sui client publish - Copy the Package ID from output
- Update
PACKAGE_IDin your code
- Check file size (< 10 MB for free tier)
- Verify network connectivity
- Try direct curl upload to test
# Clear and rebuild
rm -rf node_modules dist
npm install
npm run build- Switch network:
sui client switch --env mainnet - Deploy contract:
sui client publish --gas-budget 100000000 - Update client:
new VersionFSClient(key, 'mainnet', packageId) - Use mainnet Walrus endpoints (when available)
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details
Built with β€οΈ for the decentralized web
- Mysten Labs for Sui and Walrus
- The Move language community
- All contributors
Note: This is testnet software. Use at your own risk. Do not store sensitive or critical data.