| Crates.io | sui-mvr |
| lib.rs | sui-mvr |
| version | 0.1.0 |
| created_at | 2025-06-09 08:41:51.585229+00 |
| updated_at | 2025-06-09 08:41:51.585229+00 |
| description | Move Registry (MVR) plugin for Sui Rust SDK - resolve human-readable package names to addresses |
| homepage | https://github.com/Bralekfn/sui-mvr-rust |
| repository | https://github.com/Bralekfn/sui-mvr-rust |
| max_upload_size | |
| id | 1705669 |
| size | 164,442 |
The first Rust implementation of the Move Registry (MVR) plugin for the Sui blockchain.
Transform cryptic package addresses into human-readable names in your Rust applications. No more copy-pasting 0x80d7de9c4a56194087e0ba0bf59492aa8e6a5ee881606226930827085ddf2332 - just use @suifrens/core!
@suifrens/core β 0x123...Add this to your Cargo.toml:
[dependencies]
sui-mvr = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
Basic usage:
use sui_mvr::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a resolver for mainnet
let resolver = MvrResolver::mainnet();
// Resolve a package name to its address
let address = resolver.resolve_package("@suifrens/core").await?;
println!("SuiFrens core package: {}", address);
// Resolve a type name
let type_sig = resolver.resolve_type("@suifrens/core::suifren::SuiFren").await?;
println!("SuiFren type: {}", type_sig);
Ok(())
}
use sui_mvr::*;
use tokio::time::Duration;
// Custom configuration
let config = MvrConfig::mainnet()
.with_cache_ttl(Duration::from_secs(1800)) // 30 min cache
.with_timeout(Duration::from_secs(30)); // 30 sec timeout
let resolver = MvrResolver::new(config);
use sui_mvr::*;
use std::collections::HashMap;
// Perfect for local development and CI
let overrides = MvrOverrides::new()
.with_package("@myapp/core".to_string(), "0x123456".to_string())
.with_type("@myapp/core::Token".to_string(), "0x123456::token::Token".to_string());
let resolver = MvrResolver::testnet().with_overrides(overrides);
// This uses the override instead of making an API call
let address = resolver.resolve_package("@myapp/core").await?;
// Resolve multiple packages at once
let package_names = vec!["@suifrens/core", "@suifrens/accessories"];
let results = resolver.resolve_packages(&package_names).await?;
for (name, address) in results {
println!("{} -> {}", name, address);
}
// Batch type resolution
let type_names = vec![
"@suifrens/core::suifren::SuiFren",
"@suifrens/core::bullshark::Bullshark"
];
let type_results = resolver.resolve_types(&type_names).await?;
use sui_mvr::MvrError;
match resolver.resolve_package("@myapp/core").await {
Ok(address) => println!("β Resolved: {}", address),
Err(MvrError::PackageNotFound(name)) => {
println!("Package {} not found, using fallback", name);
// Use fallback address
}
Err(MvrError::RateLimitExceeded { retry_after_secs }) => {
println!("Rate limited, retry in {} seconds", retry_after_secs);
tokio::time::sleep(Duration::from_secs(retry_after_secs)).await;
// Retry logic
}
Err(e) if e.is_retryable() => {
println!("Retryable error: {}", e);
// Implement retry with exponential backoff
}
Err(e) => println!("Permanent error: {}", e),
}
// Get cache statistics
let stats = resolver.cache_stats()?;
println!("Cache utilization: {:.1}%", stats.utilization() * 100.0);
println!("Hit rate: {:.1}%", stats.hit_rate() * 100.0);
// Cleanup expired entries
let removed = resolver.cleanup_expired_cache()?;
println!("Cleaned up {} expired entries", removed);
// Clear entire cache
resolver.clear_cache()?;
| Operation | Individual Requests | Batch Request | Improvement |
|---|---|---|---|
| 4 packages | ~400ms | ~120ms | 3.3x faster |
| 8 packages | ~800ms | ~150ms | 5.3x faster |
| Cache hits | ~0.1ms | ~0.1ms | Instant β‘ |
| Feature | TypeScript SDK | sui-mvr (Rust) |
|---|---|---|
| Package Resolution | β | β |
| Type Resolution | β | β |
| Basic Caching | β | β |
| Static Overrides | β | β |
| Batch Resolution | β | β |
| Cache Statistics | β | β |
| Configurable TTL | β | β |
| Error Fallbacks | β | β |
| Retry Logic | β | β |
| Rate Limiting | β | β |
| Performance Metrics | β | β |
// Pre-configured endpoints
let mainnet = MvrResolver::mainnet(); // https://mainnet.mvr.mystenlabs.com
let testnet = MvrResolver::testnet(); // https://testnet.mvr.mystenlabs.com
// Custom endpoint
let custom = MvrConfig::default()
.with_endpoint("https://my-mvr-endpoint.com".to_string());
let config = MvrConfig::mainnet()
.with_cache_ttl(Duration::from_secs(3600)) // 1 hour
.with_timeout(Duration::from_secs(30)); // 30 seconds
// Save overrides
let json = overrides.to_json()?;
std::fs::write("overrides.json", json)?;
// Load overrides
let json = std::fs::read_to_string("overrides.json")?;
let overrides = MvrOverrides::from_json(&json)?;
let resolver = MvrResolver::testnet().with_overrides(overrides);
Check out the examples directory for complete working examples:
Run examples with:
cargo run --example basic_usage
cargo run --example with_overrides
cargo run --example batch_operations
# Run all tests
cargo test
# Run with coverage
cargo install cargo-tarpaulin
cargo tarpaulin --all-features
# Test examples
cargo run --example basic_usage
The crate provides comprehensive error types:
pub enum MvrError {
PackageNotFound(String), // 404 errors
TypeNotFound(String), // Type resolution failures
RateLimitExceeded { retry_after_secs: u64 }, // 429 errors
Timeout { timeout_secs: u64 }, // Network timeouts
ServerError { status_code: u16, message: String }, // 5xx errors
InvalidPackageName(String), // Validation errors
InvalidTypeName(String), // Format errors
HttpError(reqwest::Error), // Network errors
JsonError(serde_json::Error), // Parsing errors
CacheError(String), // Cache operations
ConfigError(String), // Configuration issues
}
Each error type provides:
error.is_retryable()error.is_rate_limited()error.retry_delay()We love contributions! Please see CONTRIBUTING.md for details on:
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Made with β€οΈ for the Sui community β’ Star β this repo if it helped you!