| Crates.io | nova-sdk-rs |
| lib.rs | nova-sdk-rs |
| version | 1.0.3 |
| created_at | 2025-10-09 12:27:39.786312+00 |
| updated_at | 2026-01-23 08:59:53.532411+00 |
| description | Lightweight Rust SDK for NOVA: Secure group-based file sharing on NEAR Protocol with Shade/TEE + fees model. |
| homepage | |
| repository | https://github.com/jcarbonnell/nova/tree/main/nova-sdk-rs |
| max_upload_size | |
| id | 1875500 |
| size | 175,434 |
Version: 1.0.3
License: MIT
Network: NEAR Protocol Mainnet
Crates: nova-sdk-rs
A Rust SDK for NOVA's secure, decentralized file-sharing primitive on NEAR. NOVA hybridizes on-chain access control with off-chain TEE-secured keys via Shade Agents, using nonce-based ed25519-signed tokens for ephemeral, verifiable access. This ensures privacy-first data sharing for AI datasets, healthcare/financial records, and sensitive documents.
Add to Cargo.toml:
[dependencies]
nova-sdk-rs = "1.0.3"
tokio = { version = "1", features = ["full"] }
chrono = "0.4"
NOVA v1.0.0 operates on NEAR mainnet by default. All operations consume real NEAR tokens.
Typical costs:
For development, use testnet configuration.
use nova_sdk_rs::{NovaSdk, NovaSdkConfig};
use std::fs;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize SDK with API key
let config = NovaSdkConfig::default()
.with_api_key(&std::env::var("NOVA_API_KEY")?);
let sdk = NovaSdk::with_config("alice.nova-sdk.near", config)?;
// For testnet development:
// let sdk = NovaSdk::testnet("alice.nova-sdk-5.testnet")?;
// Verify connection
println!("Network: {} | Contract: {}", sdk.network_id(), sdk.contract_id());
// Register group
sdk.register_group("my-secure-files").await?;
// Upload file (client-side encryption)
let file_data = fs::read("./confidential.pdf")?;
let result = sdk.upload(
"my-secure-files",
&file_data,
"confidential.pdf"
).await?;
println!("ā
Uploaded: {}", result.cid);
println!("š Transaction: {}", result.trans_id);
// Retrieve file (client-side decryption)
let retrieved = sdk.retrieve(
"my-secure-files",
&result.cid
).await?;
fs::write("./decrypted.pdf", &retrieved.data)?;
println!("ā
Decrypted!");
Ok(())
}
Groups manage shared access to encrypted files. Each group has:
group_id)NOVA uses signed tokens for key access:
All data is encrypted client-side using AES-256-GCM:
File metadata (CID/hash) is recorded on-chain automatically during composite_upload.
// Query group transactions
let txs = sdk.get_transactions_for_group("my_group", None).await?;
for tx in txs {
println!("File: {} | IPFS: {}", tx.file_hash, tx.ipfs_hash);
}
The SDK uses API keys for secure authentication. Get your key at nova-sdk.com:
# Store in .env (never commit to git!)
NOVA_ACCOUNT_ID=alice.nova-sdk.near
NOVA_API_KEY=nova_sk_xxxxxxxxxxxxxxxxxxxxx
use nova_sdk_rs::{NovaSdk, NovaSdkConfig};
// Initialize with API key
let config = NovaSdkConfig::default()
.with_api_key(&std::env::var("NOVA_API_KEY")?);
let sdk = NovaSdk::with_config("alice.nova-sdk.near", config)?;
// Force refresh session token if needed
sdk.refresh_token().await?;
Note: One API key per account. Generating a new key invalidates the old one.
use nova_sdk_rs::{NovaSdk, NovaSdkConfig};
// Standard usage (mainnet) - API key required
let config = NovaSdkConfig::default()
.with_api_key(&std::env::var("NOVA_API_KEY")?);
let sdk = NovaSdk::with_config("alice.nova-sdk.near", config)?;
// Testnet
let config = NovaSdkConfig::testnet()
.with_api_key(&std::env::var("NOVA_API_KEY")?);
let sdk = NovaSdk::with_config("alice.nova-sdk-5.testnet", config)?;
// Force session token refresh if needed
sdk.refresh_token().await?;
// Check authorization
sdk.auth_status(Some("my-group")).await?;
// Register group
sdk.register_group("my-group").await?;
// Add member
sdk.add_group_member("my-group", "bob.near").await?;
// Revoke member
sdk.revoke_group_member("my-group", "bob.near").await?;
// Upload (encrypts locally, uploads to IPFS, records on NEAR)
let result = sdk.upload(group_id, &data, filename).await?;
// Returns: UploadResult { cid, trans_id, file_hash }
// Retrieve (fetches from IPFS, decrypts locally)
let retrieved = sdk.retrieve(group_id, ipfs_hash).await?;
// Returns: RetrieveResult { data, ipfs_hash, group_id }
Deprecated methods (still work, but emit warnings):
// Use upload() instead
sdk.composite_upload(group_id, &data, filename).await?;
// Use retrieve() instead
sdk.composite_retrieve(group_id, ipfs_hash).await?;
The SDK uses a custom NovaError enum:
use nova_sdk_rs::NovaError;
match sdk.upload("my_group", b"data", "file.txt").await {
Ok(result) => println!("CID: {}", result.cid),
Err(NovaError::Near(msg)) => eprintln!("RPC error: {}", msg),
Err(NovaError::Mcp(msg)) => eprintln!("MCP server error: {}", msg),
Err(NovaError::Auth(msg)) => eprintln!("Authentication error: {}", msg),
Err(NovaError::Token(msg)) => eprintln!("Token error: {}", msg),
Err(NovaError::InvalidCid(cid)) => eprintln!("Invalid CID: {}", cid),
Err(NovaError::ParseAccount) => eprintln!("Invalid account ID"),
Err(NovaError::Http(msg)) => eprintln!("HTTP error: {}", msg),
Err(NovaError::Encryption(msg)) => eprintln!("Encryption error: {}", msg),
Err(NovaError::Decryption(msg)) => eprintln!("Decryption error: {}", msg),
sdk.network_id() before operationsSee the examples directory for complete working examples:
simple_upload.rs - Basic file uploadgroup_management.rs - Managing groups and membersContributions are welcome! Please:
cargo test)MIT LICENSE - Copyright (c) 2026 CivicTech OĆ