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
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
Sourcepub async fn withdraw(
&self,
onchain_address: &Address,
target_amount_sats: Option<u64>,
) -> Result<CoopExitResponse, SparkSdkError>
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 senttarget_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 IDErr(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.
Sourcepub fn create_connector_refund_transaction(
&self,
sequence: u32,
node_outpoint: OutPoint,
connector_output: OutPoint,
amount_sats: u64,
receiver_pubkey: &PublicKey,
) -> Transaction
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 transactionnode_outpoint
- The outpoint of the node transactionconnector_output
- The connector outputamount_sats
- The amount in satoshisreceiver_pubkey
- The receiver public key
§Returns
The created refund transaction
Source§impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn generate_deposit_address(
&self,
) -> Result<GenerateDepositAddressSdkResponse, SparkSdkError>
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:
- Creating a new signing keypair for the deposit address
- Requesting a deposit address from the Spark network
- Validating the returned address and proof of possession
§Returns
Ok(GenerateDepositAddressSdkResponse)
- Contains the validated deposit address and signing public keyErr(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);
Sourcepub async fn claim_deposit(
&self,
txid: String,
) -> Result<Vec<TreeNode>, SparkSdkError>
pub async fn claim_deposit( &self, txid: String, ) -> Result<Vec<TreeNode>, SparkSdkError>
Claims a pending deposit by txid
- Querying if the txid is a pending deposit
- Checking the mempool for transaction
- 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();
}
Sourcepub async fn finalize_deposit(
&self,
signing_pubkey: Vec<u8>,
verifying_pubkey: Vec<u8>,
deposit_tx: Transaction,
vout: u32,
) -> Result<Vec<TreeNode>, SparkSdkError>
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 signingdeposit_tx
- The Bitcoin transaction containing the depositvout
- 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 TreeNode
s on success
Sourcepub async fn query_unused_deposit_addresses(
&self,
) -> Result<Vec<DepositAddressQueryResult>, SparkSdkError>
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 successfulErr(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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn get_lightning_receive_fee_estimate(
&self,
amount: u64,
) -> Result<SparkFeeEstimate, SparkSdkError>
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 satoshisErr(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);
Sourcepub async fn get_lightning_send_fee_estimate(
&self,
invoice: String,
) -> Result<SparkFeeEstimate, SparkSdkError>
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 satoshisErr(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");
}
Sourcepub async fn get_cooperative_exit_fee_estimate(
&self,
leaf_ids: Vec<String>,
on_chain_address: String,
) -> Result<SparkFeeEstimate, SparkSdkError>
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 withdrawon_chain_address
- The Bitcoin address where you want to receive the funds
§Returns
Ok(SparkFeeEstimate)
- Contains the estimated fees in satoshisErr(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?;
}
Sourcepub async fn get_leaves_swap_fee_estimate(
&self,
total_amount_sats: u64,
) -> Result<SparkFeeEstimate, SparkSdkError>
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 satoshisErr(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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn new(
network: SparkNetwork,
signer: Arc<S>,
) -> Result<Self, SparkSdkError>
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();
}
Sourcepub fn get_spark_address(&self) -> Result<PublicKey, SparkSdkError>
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);
Sourcepub fn get_network(&self) -> SparkNetwork
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
SparkNetwork::Mainnet
- Production Bitcoin mainnet environmentSparkNetwork::Regtest
- Testing environment using Lightspark’s regtest network
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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub fn get_bitcoin_balance(&self) -> u64
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 satoshisErr(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);
}
Sourcepub async fn sync_wallet(&self) -> Result<(), SparkSdkError>
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:
- Claims all pending Bitcoin transfers that have been sent to you
- Refreshes timelock nodes to handle any mature timelocked funds
- Synchronizes all leaves (UTXOs) with the Spark network
- 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 successfullyErr(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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn pay_lightning_invoice(
&self,
invoice: &String,
) -> Result<Uuid, SparkSdkError>
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:
- You provide your leaves (UTXOs) to the SSP
- The SSP makes the Lightning payment on your behalf
- 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 statusErr(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.
Sourcepub async fn create_lightning_invoice(
&self,
amount_sats: u64,
memo: Option<String>,
expiry_seconds: Option<i32>,
) -> Result<Bolt11Invoice, SparkSdkError>
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:
- Generating a secure payment preimage and hash
- Creating the invoice through the SSP
- Distributing preimage shares to Spark operators using threshold secret sharing
- Returning the formatted BOLT11 invoice
§Arguments
amount_sats
- The amount in satoshis that you want to receivememo
- Optional description/memo for the invoiceexpiry_seconds
- Optional expiry time in seconds (defaults to 30 days if not specified)
§Returns
Ok(Bolt11Invoice)
- The generated Lightning invoice if successfulErr(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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn request_leaves_swap(
&self,
target_amount: u64,
) -> Result<String, SparkSdkError>
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:
- Locking all your available Bitcoin leaves
- Preparing leaf key tweaks for each leaf
- Creating a transfer to the SSP with all your available leaves
- Using cryptographic adaptor signatures for security
- Requesting new leaves from the SSP with your desired target amount
- Verifying the cryptographic integrity of the returned leaves
- Completing the swap process and claiming the new leaves
- 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 successfulErr(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>
impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S>
Sourcepub async fn query_pending_transfers(
&self,
) -> Result<Vec<Transfer>, SparkSdkError>
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 pendingTransfer
objects if successfulErr(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);
}
Sourcepub async fn transfer(
&self,
amount: u64,
receiver_spark_address: &PublicKey,
) -> Result<String, SparkSdkError>
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:
- Selecting appropriate leaves (UTXOs) that contain sufficient funds for the transfer
- Locking the selected leaves to prevent concurrent usage
- Generating new signing keys for the transfer
- Creating and signing the transfer transaction
- 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.
pub async fn transfer_leaf_ids( &self, leaf_ids: Vec<String>, receiver_identity_pubkey: &PublicKey, ) -> Result<String, SparkSdkError>
Sourcepub async fn claim_transfer(
&self,
transfer: Transfer,
) -> Result<(), SparkSdkError>
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:
- Verifies the transfer is in the correct state (SenderKeyTweaked)
- Verifies and decrypts the leaf private keys using the wallet’s identity key
- Generates new signing keys for the claimed leaves
- 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 claimedErr(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();
}
}
pub async fn claim_transfers(&self) -> Result<(), SparkSdkError>
pub async fn claim_transfers_internal(&self) -> Result<(), SparkSdkError>
pub async fn get_all_transfers( &self, limit: Option<u32>, offset: Option<u32>, ) -> Result<GetAllTransfersResponse, SparkSdkError>
Trait Implementations§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request