Struct SparkSdk

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

SparkSdk is the main struct for the Spark wallet

Implementations§

Source§

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

Source§

impl SparkSdk

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.

§Arguments
  • onchain_address - The Bitcoin address where the funds should be sent
  • target_amount_sats - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds
§Returns

The withdrawal request details, or an error if the request cannot be completed

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>

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>

Source

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

Source

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

Source

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

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 the derivation path (TODO: add 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_btc_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_btc_balance();
    println!("Balance: {}", balance);
}
Source

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

Source§

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

Source

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

Source

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

Create a Lightning invoice with a preimage and a memo.

The invoice will be valid for 30 days by default.

Source§

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

Source

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

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);
}
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 get_all_transfers( &self, limit: Option<u32>, offset: Option<u32>, ) -> Result<QueryAllTransfersResponse, 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, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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