1 unstable release
0.1.0 | Mar 5, 2025 |
---|
#8 in #kit
140 downloads per month
11KB
Spark Wallet SDK
A Rust-based Bitcoin wallet SDK for the Spark protocol that provides advanced cryptographic operations, transaction management, and Lightning Network capabilities.
Overview
Spark Wallet SDK is a comprehensive toolkit designed to manage Bitcoin transactions through a structured "tree" of UTXOs. It provides a safe, reliable interface for interacting with Bitcoin and Lightning Network functionality, with advanced features like threshold signatures.
Key Features
- Deposit Address Generation - Create secure Bitcoin addresses for receiving funds
- UTXO Tree Management - Organize UTXOs in a hierarchical tree structure for efficient management
- Cooperative Signing - Coordinate transaction signing between multiple parties
- Threshold Signatures - Support for FROST-based threshold Schnorr signatures
- Lightning Network Integration - Invoice creation and payment capabilities
- Robust Error Handling - Comprehensive error types and recovery mechanisms
- Configurable Backend - Connect to mainnet or regtest networks
Installation
Add Spark Wallet SDK to your Cargo.toml
:
[dependencies]
spark-sdk = { git = "https://github.com/polarity/spark-rs.git", features = ["self-signing"] }
Architecture
The SDK is structured around a central SparkSdk
struct that provides access to all functionality through a set of handlers:
spark-sdk/
├── src/
│ ├── wallet/
│ │ ├── handlers/ # Public API for wallet operations
│ │ ├── internal_handlers/ # Lower-level implementation details
│ │ ├── leaf_manager/ # UTXO tree management
│ │ └── client.rs # Main SparkSdk implementation
│ ├── signer/ # Cryptographic signing operations
│ ├── rpc/ # Communication with Spark services
│ └── error/ # Error handling
└── examples/ # Usage examples
Usage
Initializing the SDK
use spark_sdk::{SparkSdk, SparkNetwork, signer::default_signer::DefaultSigner};
use rand::rngs::OsRng;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Generate a random master seed (or load from secure storage)
let mut rng = OsRng;
let master_seed = bitcoin::secp256k1::SecretKey::new(&mut rng);
// Create a signer with the seed
let network = SparkNetwork::Regtest;
let signer = DefaultSigner::from_master_seed(
&master_seed.secret_bytes().to_vec(),
network
).await?;
// Initialize the SDK
let sdk = SparkSdk::new(network, signer).await?;
// SDK is now ready to use
Ok(())
}
Generating a Deposit Address
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize SDK (see above)
let sdk = get_initialized_sdk().await?;
// Generate a deposit address
let response = sdk.generate_deposit_address().await?;
println!("Deposit to: {}", response.deposit_address.address);
Ok(())
}
Creating a UTXO Tree
use bitcoin::Transaction;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sdk = get_initialized_sdk().await?;
// After receiving funds at a deposit address
// deposit_tx contains the transaction that sent funds to your deposit address
let deposit_tx = Transaction::default(); // Replace with actual transaction
// Create a tree with split level 2 (creating 4 leaf nodes)
let split_level = 2;
// Create the tree
let result = sdk.create_tree(
Some(deposit_tx),
None, // No parent node ID (creating from deposit)
0, // UTXO output index
split_level,
vec![] // No parent public keys
).await?;
println!("Created {} nodes in tree", result.nodes.len());
Ok(())
}
Transferring Funds
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sdk = get_initialized_sdk().await?;
// Transfer 50,000 satoshis to recipient
let recipient_pubkey = vec![/* public key bytes */];
let amount_sats = 50_000;
let transfer_id = sdk.transfer(amount_sats, recipient_pubkey).await?;
println!("Transfer initiated with ID: {}", transfer_id);
Ok(())
}
Creating a Lightning Invoice
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sdk = get_initialized_sdk().await?;
// Create an invoice for 10,000 satoshis
let amount_msat = 10_000_000; // 10,000 sats in millisats
let description = "Payment for services".to_string();
let invoice = sdk.create_lightning_invoice(amount_msat, description).await?;
println!("Lightning invoice: {}", invoice.bolt11);
Ok(())
}
Feature Flags
The SDK supports several feature flags to enable different functionality:
self-signing
(default): Enable local key generation and storageintegration-tests
(default): Enable concurrency and advanced integration testslocal-operator-tests
: Run tests with local Spark operatorslightning
: Enable Lightning Network functionality
Example with specific features:
[dependencies]
spark-sdk = { git = "https://github.com/polarity/spark-rs.git", features = ["self-signing", "lightning"] }
Handler Modules
The SDK is organized into handler modules, each focusing on specific functionality:
Handler | Purpose | Example Methods |
---|---|---|
init |
SDK initialization | new() , new_with_default_config() |
deposit |
Fund reception | generate_deposit_address() |
create_tree |
UTXO structuring | create_tree() |
leaves |
UTXO management | get_available_leaves() |
transfer |
Fund movement | transfer() , claim_transfer() |
lightning |
LN operations | create_lightning_invoice() , pay_invoice() |
split |
UTXO division | split_leaf() |
swap |
Atomic exchanges | initiate_swap() |
Error Handling
The SDK provides a comprehensive error type through SparkSdkError
that covers:
- Connection issues
- Authentication failures
- Transaction validation errors
- Signing problems
- Local storage issues
Example error handling:
match sdk.generate_deposit_address().await {
Ok(response) => {
println!("Success! Address: {}", response.deposit_address.address);
},
Err(e) => match e {
SparkSdkError::AuthenticationError(_) => {
println!("Authentication failed. Please re-initialize the SDK.");
},
SparkSdkError::ConnectionError(_) => {
println!("Connection to Spark service failed. Check your internet connection.");
},
_ => {
println!("An error occurred: {}", e);
}
}
}
Advanced Usage
Custom Signers
You can implement the SparkSigner
trait to provide your own signing mechanism:
use spark_sdk::signer::traits::SparkSigner;
struct MyCustomSigner {
// Your implementation details
}
#[async_trait::async_trait]
impl SparkSigner for MyCustomSigner {
// Implement required methods
}
// Then use it with the SDK
let sdk = SparkSdk::new(SparkNetwork::Regtest, my_custom_signer).await?;
Working with FROST Threshold Signatures
// Generate threshold signing commitments (for a t-of-n scheme)
let commitments = sdk.new_frost_signing_commitments().await?;
// Distribute commitments to participants
// ...
// Later, receive signature shares and aggregate them
let signature = sdk.aggregate_frost_signature_shares(message, shares).await?;
Security Considerations
- Seed Management: Properly secure the master seed used to initialize the signer
- Network Traffic: All API calls are encrypted, but be aware of the network you're connected to
- Key Rotation: Consider implementing key rotation for long-lived applications
- Backup: Implement backup functionality for critical wallet data
For Contributors
See the CONTRIBUTING.md file for guidelines on contributing to this project.
Development Setup
# Clone the repository
git clone https://github.com/polarity/spark-rs.git
cd spark-rs
# Build the SDK
cargo build -p spark-sdk
# Run tests
cargo test -p spark-sdk
Running the Examples
# Run the new wallet example
cargo run --example new_wallet
# Run the deposit example
cargo run --example deposit
License
This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.