Struct SparkSdk

Source
pub struct SparkSdk<S: SparkSigner + Send + Sync = DefaultSigner> { /* private fields */ }
Expand description

The main interface for the Spark wallet SDK

SparkSdk is the primary point of interaction with the Spark protocol, providing a complete set of wallet functionality for Bitcoin and Lightning operations. It coordinates between the cryptographic signer, wallet configuration, and leaf (UTXO) management components.

The SDK supports a pluggable signer architecture through its generic parameter, allowing applications to use either the provided DefaultSigner or implement their own custom signing solution (e.g., for hardware wallet integration).

Key functionality provided by the SDK includes:

  • Initialization: Create and set up a new wallet instance
  • Deposits: Generate deposit addresses and deposit trees
  • Transfers: Send funds to other Spark users or Bitcoin addresses
  • Lightning: Make and receive Lightning Network payments
  • Leaves: Manage individual UTXOs within the wallet
  • Swaps: Swap funds between different payment channels
  • Timelocks: Manage timelock conditions for funds
  • Fees: Estimate and manage transaction fees

§Examples

use spark_rust::{
    error::SparkSdkError,
    signer::default_signer::DefaultSigner,
    signer::traits::SparkSigner,
    SparkNetwork, SparkSdk,
};
use std::sync::Arc;

async fn example() -> Result<(), SparkSdkError> {
    // Initialize with a mnemonic phrase and network
    let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
    let network = SparkNetwork::Regtest;
     
    // Create the signer
    let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await?;
     
    // Initialize the SDK
    let sdk = SparkSdk::new(network, signer).await?;
     
    // Get wallet information
    let address = sdk.get_spark_address()?;
    println!("Spark address: {}", hex::encode(address.serialize()));
     
    // Use other SDK functionality...
     
    Ok(())
}

§Security Considerations

The Spark SDK architecture implements security through several layers:

§SDK Architecture Security

  • Separation of concerns: The SDK delegates all key operations to the signer component
  • Secure API communication with Spark operators using authenticated sessions
  • Protocol-level validation of all operator responses
  • Thread-safe access to shared resources

§Signer Security (using DefaultSigner)

  • BIP39 mnemonic-based key generation with proper entropy
  • BIP32/BIP44 compliant hierarchical deterministic key derivation
  • Secure storage of private keys with optional encryption
  • Explicit methods for sensitive operations with clear security warnings

§Spark Protocol Security

  • Threshold signature schemes (FROST) requiring multiple parties to sign transactions
  • Defense in depth through multiple security mechanisms
  • Timelocked refund transactions as safety guarantees
  • Verifiable cryptographic proofs for key operations

Note: This is an early version of the SDK, and future updates will further enhance isolation and security properties.

Implementations§

Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

CoopExitService implementation for Rust This is a 1-to-1 port of the TypeScript CoopExitService class

Source

pub async fn withdraw( &self, onchain_address: &Address, target_amount_sats: Option<u64>, ) -> Result<CoopExitResponse, SparkSdkError>

Initiates a withdrawal to move funds from the Spark network to an on-chain Bitcoin address.

This function allows you to exit the Spark network by withdrawing funds back to the Bitcoin blockchain through a cooperative process with the Spark Service Provider (SSP). The SSP facilitates the on-chain transaction and charges a service fee for this operation.

§Arguments
  • onchain_address - The Bitcoin address where the funds should be sent
  • target_amount_sats - Optional amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds in your wallet
§Returns
  • Ok(CoopExitResponse) - Contains the cooperative exit request ID and exit transaction ID
  • Err(SparkSdkError) - If the withdrawal request failed
§Example
// Create a Bitcoin address to receive the funds
let address = Address::from_str("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")?.require_network(Network::Regtest).unwrap();

// Withdraw all available funds
let response = sdk.withdraw(&address, None).await?;
println!("Withdrawal initiated with request ID: {:?}", response.request_id);
println!("Exit transaction ID: {}", response.exit_txid);

// Or withdraw a specific amount (e.g., 50,000 satoshis)
// let response = sdk.withdraw(&address, Some(50_000)).await?;
§Note

Withdrawals incur a service fee charged by the SSP. You can estimate this fee before initiating a withdrawal using the get_cooperative_exit_fee_estimate method.

Source

pub fn create_connector_refund_transaction( &self, sequence: u32, node_outpoint: OutPoint, connector_output: OutPoint, amount_sats: u64, receiver_pubkey: &PublicKey, ) -> Transaction

Creates a connector refund transaction.

This method is equivalent to the TypeScript createConnectorRefundTransaction method. It creates a refund transaction for a connector output.

§Arguments
  • sequence - The sequence number for the transaction
  • node_outpoint - The outpoint of the node transaction
  • connector_output - The connector output
  • amount_sats - The amount in satoshis
  • receiver_pubkey - The receiver public key
§Returns

The created refund transaction

Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn generate_deposit_address( &self, ) -> Result<GenerateDepositAddressSdkResponse, SparkSdkError>

Generates a new deposit address for receiving funds into the Spark wallet.

This function handles the generation of a new deposit address by:

  1. Creating a new signing keypair for the deposit address
  2. Requesting a deposit address from the Spark network
  3. Validating the returned address and proof of possession
§Returns
  • Ok(GenerateDepositAddressSdkResponse) - Contains the validated deposit address and signing public key
  • Err(SparkSdkError) - If there was an error during address generation
§Errors

Returns SparkSdkError if:

  • Failed to generate new signing keypair
  • Network errors when communicating with Spark operators
  • Address validation fails (e.g. invalid proof of possession)
§Example
let deposit_address = sdk.generate_deposit_address().await?;
println!("New deposit address: {}", deposit_address.deposit_address);
Source

pub async fn claim_deposit( &self, txid: String, ) -> Result<Vec<TreeNode>, SparkSdkError>

Claims a pending deposit by txid

  1. Querying if the txid is a pending deposit
  2. Checking the mempool for transaction
  3. Finalizing the deposit by creating tree nodes
§Errors

Returns SparkSdkError if:

  • Failed to connect to Spark service
  • Failed to query mempool
  • Failed to finalize deposits
§Example

async fn example() {
    let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
    let network = SparkNetwork::Regtest;
    let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
    let sdk = SparkSdk::new(network, signer).await.unwrap();

    let hardcoded_txid = "edb5575e6ee96fcf175c9114e0b0d86d99d4642956edcd02e6ec7b6899e90b41";
    sdk.claim_deposit(hardcoded_txid.to_string()).await.unwrap();
}
Source

pub async fn finalize_deposit( &self, signing_pubkey: Vec<u8>, verifying_pubkey: Vec<u8>, deposit_tx: Transaction, vout: u32, ) -> Result<Vec<TreeNode>, SparkSdkError>

Finalizes a deposit by creating a tree node and transferring it to self

§Arguments
  • signing_pubkey - The public key used for signing
  • deposit_tx - The Bitcoin transaction containing the deposit
  • vout - The output index in the transaction
§Errors

Returns SparkSdkError if:

  • Failed to create tree node
  • Failed to transfer deposits
§Returns

Returns an empty vector of TreeNodes on success

Source

pub async fn query_unused_deposit_addresses( &self, ) -> Result<Vec<DepositAddressQueryResult>, SparkSdkError>

Retrieves all unused deposit addresses that have been previously generated for your wallet.

This function queries the Spark network for all deposit addresses associated with your identity public key that haven’t been used for deposits yet. This helps you track deposit addresses that you’ve created but haven’t received funds on yet.

§Returns
  • Ok(Vec<DepositAddressQueryResult>) - A vector of unused deposit addresses if successful
  • Err(SparkSdkError) - If there was an error querying the addresses
§Example
// Query all unused deposit addresses associated with your wallet
let unused_addresses = sdk.query_unused_deposit_addresses().await?;

// Process each unused address
for address_result in unused_addresses {
    println!("Unused address: {}", address_result.deposit_address);
}
Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn get_lightning_receive_fee_estimate( &self, amount: u64, ) -> Result<SparkFeeEstimate, SparkSdkError>

Estimates the fees for receiving a Lightning payment through the Spark Service Provider (SSP).

This function calculates how much the SSP will charge for facilitating the receipt of a Lightning payment of the specified amount. The fee is deducted from the received amount before it is credited to your wallet.

§Arguments
  • amount - The amount in satoshis you want to receive
§Returns
  • Ok(SparkFeeEstimate) - Contains the estimated fees in satoshis
  • Err(SparkSdkError) - If there was an error estimating the fees
§Example
// Get fee estimate for receiving 50,000 satoshis
let amount = 50_000;
let fee_estimate = sdk.get_lightning_receive_fee_estimate(amount).await?;
println!("The SSP will charge {} sats for receiving {} sats", fee_estimate.fees, amount);

// Calculate net amount after fees
let net_amount = amount - fee_estimate.fees;
println!("You'll receive {} sats after fees", net_amount);
Source

pub async fn get_lightning_send_fee_estimate( &self, invoice: String, ) -> Result<SparkFeeEstimate, SparkSdkError>

Estimates the fees for sending a Lightning payment through the Spark Service Provider (SSP).

This function calculates how much the SSP will charge for facilitating a Lightning payment to the destination specified in the invoice. The fee is in addition to the invoice amount and is paid from your wallet.

§Arguments
  • invoice - The Lightning invoice you want to pay
§Returns
  • Ok(SparkFeeEstimate) - Contains the estimated fees in satoshis
  • Err(SparkSdkError) - If there was an error estimating the fees
§Example
    // Get fee estimate for a Lightning invoice
    let invoice = "lnbc1500n1p3zty3app5wkf0hagkc4egr8rl88msr4c5lp0ygt6gvzna5hdg4tpna65pzqdq0vehk7cnpwga5xzmnwvycqzpgxqyz5vqsp5v9ym7xsyf0qxqwzlmwjl3g0g9q2tg977h70hcheske9xlgfsggls9qyyssqtghx3qqpwm9zl4m398nm40wj8ryaz8v7v4rrdvczypdpy7qtc6rdrkklm9uxlkmtp3jf29yhqjw2vwmlp82y5ctft94k23cwgqd9llgy".to_string();
    let fee_estimate = sdk.get_lightning_send_fee_estimate(invoice).await?;
    println!("The SSP will charge {} sats for this Lightning payment", fee_estimate.fees);

    // Decide whether to proceed with payment based on fee amount
    if fee_estimate.fees < 100 {
        println!("Fee is acceptable, proceeding with payment");
    }
Source

pub async fn get_cooperative_exit_fee_estimate( &self, leaf_ids: Vec<String>, on_chain_address: String, ) -> Result<SparkFeeEstimate, SparkSdkError>

Estimates the fees for withdrawing funds from Spark to an on-chain Bitcoin address.

This function calculates how much the SSP will charge for facilitating the withdrawal of specific leaves from the Spark network to an on-chain Bitcoin address. The fee is deducted from the withdrawn amount.

§Arguments
  • leaf_ids - The specific leaf IDs you want to withdraw
  • on_chain_address - The Bitcoin address where you want to receive the funds
§Returns
  • Ok(SparkFeeEstimate) - Contains the estimated fees in satoshis
  • Err(SparkSdkError) - If there was an error estimating the fees
§Example
// Identify the leaves you want to withdraw
let leaf_ids = vec!["leaf_id_1".to_string(), "leaf_id_2".to_string()];

// Specify the Bitcoin address to receive funds
let onchain_address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4".to_string();

// Get fee estimate before withdrawing
let fee_estimate = sdk.get_cooperative_exit_fee_estimate(leaf_ids.clone(), onchain_address.clone()).await?;
println!("Estimated withdrawal fee: {} satoshis", fee_estimate.fees);

// Decide whether to proceed with the withdrawal based on the fee
if fee_estimate.fees < 1000 {
    // Fee is acceptable, proceed with withdrawal
    let bitcoin_address = Address::from_str(&onchain_address)?;
    // sdk.withdraw(&bitcoin_address, None).await?;
}
Source

pub async fn get_leaves_swap_fee_estimate( &self, total_amount_sats: u64, ) -> Result<SparkFeeEstimate, SparkSdkError>

Estimates the fees for optimizing your wallet’s leaf structure by swapping leaves with the SSP.

This function calculates how much the SSP will charge for facilitating a leaves swap operation. Leaf swaps are used to optimize your wallet’s UTXO structure or to obtain specific denominations needed for transfers.

§Arguments
  • total_amount_sats - The total amount in satoshis that will be involved in the swap
§Returns
  • Ok(SparkFeeEstimate) - Contains the estimated fees in satoshis
  • Err(SparkSdkError) - If there was an error estimating the fees
§Example
// Total amount to be swapped
let total_amount_sats = 100_000;

// Get fee estimate before swapping leaves
let fee_estimate = sdk.get_leaves_swap_fee_estimate(total_amount_sats).await?;
println!("Estimated swap fee: {} satoshis", fee_estimate.fees);
Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn new( network: SparkNetwork, signer: Arc<S>, ) -> Result<Self, SparkSdkError>

Creates a new instance of the Spark SDK.

This is the main entry point for interacting with the Spark protocol. It initializes the SDK with the provided network configuration, signer implementation, and optional data storage path.

§Arguments
  • network - The Spark network to connect to (e.g. Regtest or Mainnet)
  • signer - Implementation of the SparkSigner trait wrapped in Arc for thread-safe access
§Returns

Returns a Result containing either:

  • The initialized SparkSdk instance
  • A SparkSdkError if initialization fails
§Examples
use spark_rust::{
    error::SparkSdkError,
    signer::default_signer::DefaultSigner,
    signer::traits::SparkSigner,
    SparkNetwork, SparkSdk,
};

async fn init_sdk() {
    let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
    let network = SparkNetwork::Regtest;
    let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
    let sdk = SparkSdk::new(
        network,
        signer
    ).await.unwrap();
}
Source

pub fn get_spark_address(&self) -> Result<PublicKey, SparkSdkError>

Returns the Spark address of the wallet, which is the identity public key.

The Spark address is derived from the identity public key of the wallet. This key is generated when the wallet is first created and remains constant throughout the wallet’s lifetime.

The Spark address serves several purposes:

  • Authenticates the wallet with Spark operators during API calls
  • Used in deposit address generation to prove ownership
  • Required for validating operator signatures
  • Helps prevent unauthorized access to wallet funds
§Returns

A byte slice containing the 33-byte compressed secp256k1 public key in SEC format. The first byte is either 0x02 or 0x03 (the parity), followed by the 32-byte X coordinate.

§Examples

let network = SparkNetwork::Regtest;
let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
let sdk = SparkSdk::new(network, signer).await.unwrap();

// Spark address is the identity public key of the user. This is derived using Spark's custom derivation path explained in the docs.
let spark_address = sdk.get_spark_address().unwrap();

// Currently, a user's Spark address is their public key.
assert_eq!(spark_address.serialize().len(), 33);
Source

pub fn get_network(&self) -> SparkNetwork

Returns the Bitcoin network that this wallet is connected to.

The network determines which Spark operators the wallet communicates with and which Bitcoin network (mainnet or regtest) is used for transactions.

§Network Types

The network is set when creating the wallet and cannot be changed after initialization. All transactions and addresses will be created for the configured network.

§Returns

Returns a SparkNetwork enum indicating whether this is a mainnet or regtest wallet.

§Examples
let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
let network = SparkNetwork::Regtest;

// Create a DefaultSigner that implements SparkSigner
let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
let sdk = SparkSdk::new(network, signer).await.unwrap();

assert_eq!(sdk.get_network(), SparkNetwork::Regtest);
Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub fn get_bitcoin_balance(&self) -> u64

Returns the balance of the wallet in satoshis.

This function calculates the total value of all available leaves in the wallet.

§Returns
  • Ok(u64) - The total balance in satoshis
  • Err(SparkSdkError) - If there was an error accessing the leaf manager
§Example

async fn example() {
    let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
    let network = SparkNetwork::Regtest;
    let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
    let sdk = SparkSdk::new(network, signer).await.unwrap();
    let balance = sdk.get_bitcoin_balance();
    println!("Balance: {}", balance);
}
Source

pub async fn sync_wallet(&self) -> Result<(), SparkSdkError>

Performs a comprehensive synchronization of your wallet with the Spark network.

This function executes multiple synchronization operations in sequence:

  1. Claims all pending Bitcoin transfers that have been sent to you
  2. Refreshes timelock nodes to handle any mature timelocked funds
  3. Synchronizes all leaves (UTXOs) with the Spark network
  4. Optimizes leaf distribution for efficient wallet operation

This is a convenience method that ensures your wallet is fully up-to-date with the latest state from the Spark network. It’s recommended to call this periodically or whenever you need to ensure you have the most current state.

§Returns
  • Ok(()) - If all synchronization operations completed successfully
  • Err(SparkSdkError) - If there was an error during any synchronization step
§Example

// Synchronize wallet with the network
sdk.sync_wallet().await?;

// After synchronization, your wallet will have:
// - Claimed all pending transfers
// - Updated all leaves
// - Optimized the leaf structure

// Check your updated balance
let updated_balance = sdk.get_bitcoin_balance();
println!("Updated balance: {} satoshis", updated_balance);
Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn pay_lightning_invoice( &self, invoice: &String, ) -> Result<Uuid, SparkSdkError>

Pays a Lightning Network invoice using the Spark Service Provider (SSP) as an intermediary.

Unlike traditional Lightning wallets, Spark doesn’t directly connect to the Lightning Network. Instead, it uses a cooperative approach where:

  1. You provide your leaves (UTXOs) to the SSP
  2. The SSP makes the Lightning payment on your behalf
  3. The transaction is secured using cryptographic techniques

This method handles the entire process including:

  • Parsing and validating the Lightning invoice
  • Selecting appropriate leaves to cover the invoice amount
  • Executing a secure swap with the SSP
  • Finalizing the payment through the Lightning Network
§Arguments
  • invoice - A BOLT11 Lightning invoice string that you want to pay
§Returns
  • Ok(String) - The payment ID if successful, which can be used to track the payment status
  • Err(SparkSdkError) - If there was an error during the payment process
§Example
// Lightning invoice to pay
let invoice = "lnbc1500n1p3zty3app5wkf0hagkc4egr8rl88msr4c5lp0ygt6gvzna5hdg4tpna65pzqdq0vehk7cnpwga5xzmnwvycqzpgxqyz5vqsp5v9ym7xsyf0qxqwzlmwjl3g0g9q2tg977h70hcheske9xlgfsggls9qyyssqtghx3qqpwm9zl4m398nm40wj8ryaz8v7v4rrdvczypdpy7qtc6rdrkklm9uxlkmtp3jf29yhqjw2vwmlp82y5ctft94k23cwgqd9llgy".to_string();

// Pay the invoice
let payment_id = sdk.pay_lightning_invoice(&invoice).await?;
println!("Lightning payment initiated with ID: {}", payment_id);
§Note

The payment incurs a service fee charged by the SSP. You can estimate this fee before initiating the payment using the get_lightning_send_fee_estimate method.

Source

pub async fn create_lightning_invoice( &self, amount_sats: u64, memo: Option<String>, expiry_seconds: Option<i32>, ) -> Result<Bolt11Invoice, SparkSdkError>

Creates a Lightning Network invoice that others can pay to you.

This function generates a BOLT11 Lightning invoice and distributes the payment preimage using a threshold secret sharing scheme among Spark operators. When someone pays this invoice via Lightning, the funds will be received by the SSP and then transferred to your Spark wallet.

The process involves:

  1. Generating a secure payment preimage and hash
  2. Creating the invoice through the SSP
  3. Distributing preimage shares to Spark operators using threshold secret sharing
  4. Returning the formatted BOLT11 invoice
§Arguments
  • amount_sats - The amount in satoshis that you want to receive
  • memo - Optional description/memo for the invoice
  • expiry_seconds - Optional expiry time in seconds (defaults to 30 days if not specified)
§Returns
  • Ok(Bolt11Invoice) - The generated Lightning invoice if successful
  • Err(SparkSdkError) - If there was an error during invoice creation
§Example
// Create an invoice for 50,000 satoshis
let amount_sats = 50_000;
let memo = Some("Payment for services".to_string());
let expiry = Some(3600 * 24); // 24 hours

// Generate the Lightning invoice
let invoice = sdk.create_lightning_invoice(amount_sats, memo, expiry).await?;

// Get the invoice string to share with the payer
let invoice_string = invoice.to_string();
println!("Lightning Invoice: {}", invoice_string);
§Note

Receiving Lightning payments incurs a service fee charged by the SSP. You can estimate this fee before creating an invoice using the get_lightning_receive_fee_estimate method.

Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn request_leaves_swap( &self, target_amount: u64, ) -> Result<String, SparkSdkError>

Optimizes your wallet’s leaf structure by swapping your current leaves with the Spark Service Provider (SSP).

This function allows you to obtain leaves of specific denominations by swapping your existing leaves with the SSP. This is particularly useful when you need to transfer a specific amount but don’t have a leaf of that exact denomination.

For example, if you have a single leaf of 100,000 satoshis but need to send 80,000 satoshis, this function will swap with the SSP to get leaves totaling 100,000 satoshis but with denominations that include the 80,000 you need. The SSP typically provides leaves in power-of-2 denominations for optimal efficiency.

The swap process involves:

  1. Locking all your available Bitcoin leaves
  2. Preparing leaf key tweaks for each leaf
  3. Creating a transfer to the SSP with all your available leaves
  4. Using cryptographic adaptor signatures for security
  5. Requesting new leaves from the SSP with your desired target amount
  6. Verifying the cryptographic integrity of the returned leaves
  7. Completing the swap process and claiming the new leaves
  8. Deleting your old leaves
§Arguments
  • target_amount - The amount (in satoshis) you want to have in a specific leaf after the swap
§Returns
  • Ok(String) - The ID of the newly created leaf with the target amount if successful
  • Err(SparkSdkError) - If there was an error during the swap process
§Example
// Let's say you have a single leaf of 100,000 satoshis but need to send 80,000
let target_amount = 80_000;

// Request a swap with the SSP to get optimized leaves
let new_leaf_id = sdk.request_leaves_swap(target_amount).await?;
println!("Created new leaf with ID: {}", new_leaf_id);

// Now you can transfer exactly 80,000 satoshis
let receiver_spark_address = PublicKey::from_str(
    "02782d7ba8764306bd324e23082f785f7c880b7202cb10c85a2cb96496aedcaba7"
).unwrap();
sdk.transfer(target_amount, &receiver_spark_address).await?;
§Note

Leaves swaps incur a service fee charged by the SSP. You can estimate this fee before initiating a swap using the get_leaves_swap_fee_estimate method. The swap operates on all available leaves in your wallet, so the total balance will remain the same (minus fees), but the denomination structure will change.

Source§

impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>

Source

pub async fn query_pending_transfers( &self, ) -> Result<Vec<Transfer>, SparkSdkError>

Queries all pending transfers where the current user is the receiver.

This function retrieves all pending transfers that are waiting to be accepted by the current user. A pending transfer represents funds that have been sent to the user but have not yet been claimed. The transfers remain in a pending state until the receiver claims them, at which point the funds become available in their wallet.

§Returns
  • Ok(Vec<Transfer>) - A vector of pending Transfer objects if successful
  • Err(SparkSdkError) - If there was an error querying the transfers
§Example
let pending = sdk.query_pending_transfers().await?;
for transfer in pending {
    println!("Pending transfer: {:?} satoshis", transfer.total_value_sats);
}
Source

pub async fn transfer( &self, amount: u64, receiver_spark_address: &PublicKey, ) -> Result<String, SparkSdkError>

Initiates a transfer of funds to another user.

This function handles the process of transferring funds from the current user’s wallet to another user, identified by their public key. The transfer process involves several steps:

  1. Selecting appropriate leaves (UTXOs) that contain sufficient funds for the transfer
  2. Locking the selected leaves to prevent concurrent usage
  3. Generating new signing keys for the transfer
  4. Creating and signing the transfer transaction
  5. Removing the used leaves from the wallet

The transfer remains in a pending state until the receiver claims it. The expiry time is set to 30 days by default (see DEFAULT_TRANSFER_EXPIRY).

§Arguments
  • amount - The amount to transfer in satoshis. Must be greater than the dust limit and the wallet must have a leaf with exactly this amount.
  • receiver_spark_address - The Spark address identifying the receiver of the transfer. This should be the receiver’s Spark address, not a regular Bitcoin public key.
§Returns
  • Ok(String) - The transfer ID if successful. This ID can be used to track the transfer status.
  • Err(SparkSdkError) - If the transfer fails. Common error cases include:
    • No leaf with exact amount available
    • Failed to lock leaves
    • Failed to generate new signing keys
    • Network errors when communicating with Spark operators
§Example
let amount = 100_000;

// Currently, a user's Spark address is their public key.
let receiver_spark_address = PublicKey::from_str("02782d7ba8764306bd324e23082f785f7c880b7202cb10c85a2cb96496aedcaba7").unwrap();

let transfer_id_string = sdk.transfer(amount, &receiver_spark_address).await?;
let transfer_id = Uuid::parse_str(&transfer_id_string).unwrap();
println!("Transfer ID is {}", transfer_id);
§Notes

Currently, the leaf selection algorithm only supports selecting a single leaf with the exact transfer amount. Future versions will support combining multiple leaves and handling change outputs.

Source

pub async fn transfer_leaf_ids( &self, leaf_ids: Vec<String>, receiver_identity_pubkey: &PublicKey, ) -> Result<String, SparkSdkError>

Source

pub async fn claim_transfer( &self, transfer: Transfer, ) -> Result<(), SparkSdkError>

Claims a pending transfer that was sent to this wallet.

This function processes a pending transfer and claims the funds into the wallet. It performs the following steps:

  1. Verifies the transfer is in the correct state (SenderKeyTweaked)
  2. Verifies and decrypts the leaf private keys using the wallet’s identity key
  3. Generates new signing keys for the claimed leaves
  4. Finalizes the transfer by:
    • Tweaking the leaf keys
    • Signing refund transactions
    • Submitting the signatures to the Spark network
    • Storing the claimed leaves in the wallet’s database
§Arguments
  • transfer - The pending transfer to claim, must be in SenderKeyTweaked status
§Returns
  • Ok(()) - If the transfer was successfully claimed
  • Err(SparkSdkError) - If there was an error during the claim process
§Errors

Returns [SparkSdkError::InvalidInput] if:

  • The transfer is not in SenderKeyTweaked status

May also return other SparkSdkError variants for network, signing or storage errors.

§Example

async fn example() {
    let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
    let network = SparkNetwork::Regtest;
    let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
    let sdk = SparkSdk::new(network, signer).await.unwrap();
    let pending = sdk.query_pending_transfers().await.unwrap();
    for transfer in pending {
        sdk.claim_transfer(transfer).await.unwrap();
    }
}
Source

pub async fn claim_transfers(&self) -> Result<(), SparkSdkError>

Source

pub async fn claim_transfers_internal(&self) -> Result<(), SparkSdkError>

Source

pub async fn get_all_transfers( &self, limit: Option<u32>, offset: Option<u32>, ) -> Result<GetAllTransfersResponse, SparkSdkError>

Trait Implementations§

Source§

impl<S: Clone + SparkSigner + Send + Sync> Clone for SparkSdk<S>

Source§

fn clone(&self) -> SparkSdk<S>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<S> Freeze for SparkSdk<S>

§

impl<S = DefaultSigner> !RefUnwindSafe for SparkSdk<S>

§

impl<S> Send for SparkSdk<S>

§

impl<S> Sync for SparkSdk<S>

§

impl<S> Unpin for SparkSdk<S>

§

impl<S = DefaultSigner> !UnwindSafe for SparkSdk<S>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T