Cross-platform FFI bindings for the VSS (Versioned Storage Service) Rust Client, providing a simple interface for mobile applications to interact with VSS servers.
- Rust 1.75+
uniffi-bindgenfor generating bindings
# Basic build
cargo build --release
# Generate ALL bindings
./build.sh all
# Generate Swift bindings for iOS
./build_ios.sh
# Generate Kotlin bindings for Android
./build_android.sh
# Generate Python bindings
./build_python.shimport VssRustClientFfi
let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
let passphrase: String? = nil
let storeId = try vssDeriveStoreId(
prefix: "bitkit_v1_regtest",
mnemonic: mnemonic,
passphrase: passphrase
)
try await vssNewClientWithLnurlAuth(
baseUrl: "https://vss.example.com",
storeId: storeId,
mnemonic: mnemonic,
passphrase: passphrase,
lnurlAuthServerUrl: "https://auth.example.com/lnurl"
)
// Store data
let item = try await vssStore(
key: "user-settings",
value: "{'theme': 'dark'}".data(using: .utf8)!
)
print("Stored at version: \(item.version)")
// Retrieve data
if let item = try await vssGet(key: "user-settings") {
let data = String(data: item.value, encoding: .utf8)
print("Retrieved: \(data)")
}
// List all items with prefix
let items = try await vssList(prefix: "user/")
for item in items {
print("Key: \(item.key), Version: \(item.version)")
}
// Delete data
let wasDeleted = try await vssDelete(key: "user-settings")
print("Deleted: \(wasDeleted)")
// Clean shutdown (optional)
vssShutdownClient()For fully isolated LDK operations with independent key derivation (full 64-byte BIP39 seed):
// Initialize the dedicated LDK client (separate from the app client)
try await vssNewLdkClientWithLnurlAuth(
baseUrl: "https://vss.example.com",
storeId: storeId,
mnemonic: mnemonic,
passphrase: passphrase,
lnurlAuthServerUrl: "https://auth.example.com/lnurl"
)
// Read an ldk-node key
if let item = try await vssLdkGet(key: "network_graph", namespace: .default) {
print("Graph size: \(item.value.count) bytes")
}
// Store a key
let item = try await vssLdkStore(
key: "network_graph",
value: graphData,
namespace: .default
)
// Delete a key
let wasDeleted = try await vssLdkDelete(key: "network_graph", namespace: .default)
// List keys in a namespace
let keys = try await vssLdkListKeys(namespace: .monitors)
// List all keys across all namespaces
let allKeys = try await vssLdkListAllKeys()
// Clean shutdown
vssShutdownLdkClient()from vss_rust_client_ffi import *
mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
passphrase = None
store_id = vss_derive_store_id(
prefix="bitkit_v1_regtest",
mnemonic=mnemonic,
passphrase=passphrase
)
await vss_new_client_with_lnurl_auth(
"https://vss.example.com",
store_id,
mnemonic,
passphrase,
"https://auth.example.com/lnurl"
)
# Store data
item = await vss_store("user-settings", b"{'theme': 'dark'}")
print(f"Stored at version: {item.version}")
# Retrieve data
item = await vss_get("user-settings")
if item:
print(f"Retrieved: {item.value.decode()}")
# List keys only (more efficient)
keys = await vss_list_keys("user/")
for kv in keys:
print(f"Key: {kv.key}, Version: {kv.version}")
# Batch store multiple items
items_to_store = [
KeyValue(key="config/theme", value=b"dark"),
KeyValue(key="config/lang", value=b"en")
]
stored_items = await vss_put_with_key_prefix(items_to_store)
print(f"Stored {len(stored_items)} items")
# Delete data
was_deleted = await vss_delete("user-settings")
print(f"Deleted: {was_deleted}")
# Clean shutdown (optional)
vss_shutdown_client()# Initialize the dedicated LDK client (separate from the app client)
await vss_new_ldk_client_with_lnurl_auth(
"https://vss.example.com",
store_id,
mnemonic,
passphrase,
"https://auth.example.com/lnurl"
)
# Read an ldk-node key
item = await vss_ldk_get("network_graph", LdkNamespace.DEFAULT)
# Store a key
item = await vss_ldk_store("network_graph", graph_data, LdkNamespace.DEFAULT)
# Delete a key
was_deleted = await vss_ldk_delete("network_graph", LdkNamespace.DEFAULT)
# List keys in a namespace
keys = await vss_ldk_list_keys(LdkNamespace.MONITORS)
# List all keys across all namespaces
all_keys = await vss_ldk_list_all_keys()
# Clean shutdown
vss_shutdown_ldk_client()import uniffi.vss_rust_client_ffi.*
val mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
val passphrase: String? = null
val storeId = vssDeriveStoreId(
prefix = "bitkit_v1_regtest",
mnemonic = mnemonic,
passphrase = passphrase
)
vssNewClientWithLnurlAuth(
baseUrl = "https://vss.example.com",
storeId = storeId,
mnemonic = mnemonic,
passphrase = passphrase,
lnurlAuthServerUrl = "https://auth.example.com/lnurl"
)
// Store data
val item = vssStore(
key = "user-settings",
value = "{'theme': 'dark'}".toByteArray()
)
println("Stored at version: ${item.version}")
// Retrieve data
val retrievedItem = vssGet("user-settings")
retrievedItem?.let {
println("Retrieved: ${String(it.value)}")
}
// List all items
val items = vssList(prefix = null)
items.forEach { item ->
println("Key: ${item.key}, Version: ${item.version}")
}
// Clean shutdown (optional)
vssShutdownClient()// Initialize the dedicated LDK client (separate from the app client)
vssNewLdkClientWithLnurlAuth(
baseUrl = "https://vss.example.com",
storeId = storeId,
mnemonic = mnemonic,
passphrase = passphrase,
lnurlAuthServerUrl = "https://auth.example.com/lnurl"
)
// Read an ldk-node key
val item = vssLdkGet(key = "network_graph", namespace = LdkNamespace.Default)
item?.let { println("Graph size: ${it.value.size} bytes") }
// Store a key
val stored = vssLdkStore(
key = "network_graph",
value = graphData,
namespace = LdkNamespace.Default
)
// Delete a key
val wasDeleted = vssLdkDelete(key = "network_graph", namespace = LdkNamespace.Default)
// List keys in a namespace
val keys = vssLdkListKeys(namespace = LdkNamespace.Monitors)
// List all keys across all namespaces
val allKeys = vssLdkListAllKeys()
// Clean shutdown
vssShutdownLdkClient()Initialize the global VSS client connection without authentication.
baseUrl: VSS server URL (e.g., "https://vss.example.com")storeId: Unique identifier for your storage namespace
vssNewClientWithLnurlAuth(baseUrl: String, storeId: String, mnemonic: String, passphrase: String?, lnurlAuthServerUrl: String) -> Void
Initialize the global VSS client connection with LNURL-auth authentication. Provides automatic JWT token management and data encryption.
baseUrl: VSS server URL (e.g., "https://vss.example.com")storeId: Unique identifier for your storage namespacemnemonic: BIP39 mnemonic phrase (12 or 24 words)passphrase: Optional BIP39 passphrase (passnullif none)lnurlAuthServerUrl: LNURL-auth server URL for authentication
Shutdown the VSS client and clean up resources. Optional but recommended for clean application shutdown.
Derives a deterministic VSS store ID from a mnemonic and optional passphrase using BIP32 key derivation.
prefix: A prefix to include in the store ID (e.g., "bitkit_v1_regtest")mnemonic: BIP39 mnemonic phrase (12 or 24 words)passphrase: Optional BIP39 passphrase
Store a key-value pair. The server automatically manages versioning, incrementing the version number with each update.
Retrieve an item by key. Returns null if not found.
List all items, optionally filtered by key prefix. Includes full data.
List keys and versions only (more efficient than vssList).
Store multiple items in a single atomic transaction. The server manages versioning for all items.
Delete an item. Returns true if item existed and was deleted.
A fully separate client (LdkVssClient) with its own key derivation using the full 64-byte BIP39 seed, independent from the app backup client. Use this when LDK operations must be completely isolated from app backup operations.
vssNewLdkClientWithLnurlAuth(baseUrl: String, storeId: String, mnemonic: String, passphrase: String?, lnurlAuthServerUrl: String) -> Void
Initialize the dedicated LDK client with LNURL-auth authentication. This client is fully separate from the app client initialized with vssNewClientWithLnurlAuth.
Shutdown the dedicated LDK client and clean up resources.
Store a key-value pair using the dedicated LDK client.
Retrieve an item by key using the dedicated LDK client. Returns null if not found.
Delete an item using the dedicated LDK client. Returns true if item existed and was deleted.
List keys in a namespace using the dedicated LDK client.
List all keys across all singleton LDK namespaces using the dedicated LDK client.
key: String- The item keyvalue: Data- The stored dataversion: Int64- Version number
key: String- The item keyvalue: Data- The data to store
key: String- The item keyversion: Int64- Version number
Default- Default namespace (channel_manager, scorer, etc.)Monitors- Channel monitorsMonitorUpdates(monitorId)- Updates for a specific monitorArchivedMonitors- Archived channel monitors
Error enum with detailed error information for different failure scenarios.
./build_ios.shGenerates:
bindings/ios/VssRustClientFfi.xcframework- iOS frameworkbindings/ios/vss_rust_client_ffi.swift- Swift bindings
./build_android.shGenerates:
bindings/android/vss_rust_client_ffi.kt- Kotlin bindingsbindings/android/jniLibs/- Native libraries for all Android architectures
./build_python.shGenerates:
bindings/python/- Python package with bindings and native library
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install uniffi-bindgen
cargo install uniffi_bindgen# Run unit tests (recommended)
cargo test tests::tests --lib
# Check compilation
cargo check
# Build library
cargo build --release
# Test bindings generation
cargo run --bin uniffi-bindgen generate \
--library ./target/release/libvss_rust_client_ffi.dylib \
--language swift \
--out-dir ./test_bindingsThis library provides a thin FFI wrapper around the vss-client-ng Rust library, exposing a simplified async API suitable for mobile and cross-platform applications.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Run
cargo testandcargo clippy - Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- VSS Server - The VSS server implementation
- vss-client-ng - The underlying Rust client library
- UniFFI - The FFI binding generator