1 unstable release

0.1.0 Mar 5, 2025

#8 in #kit

Download history 119/week @ 2025-03-01 21/week @ 2025-03-08

140 downloads per month

Apache-2.0

11KB

Spark Wallet SDK

License: Apache-2.0 Rust Version: 1.70+

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 storage
  • integration-tests (default): Enable concurrency and advanced integration tests
  • local-operator-tests: Run tests with local Spark operators
  • lightning: 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.

No runtime deps