spark_rust/wallet/internal_handlers/traits/
transfer.rs

1use crate::common_types::types::Transaction;
2use crate::error::SparkSdkError;
3use crate::signer::traits::SparkSigner;
4use bitcoin::secp256k1::PublicKey;
5use bitcoin::secp256k1::SecretKey;
6use spark_protos::common::SigningCommitment as ProtoSigningCommitment;
7use spark_protos::spark::ClaimLeafKeyTweak;
8use spark_protos::spark::LeafRefundTxSigningJob;
9use spark_protos::spark::QueryAllTransfersResponse;
10use spark_protos::spark::SendLeafKeyTweak;
11use spark_protos::spark::Transfer;
12use spark_protos::spark::TreeNode;
13use std::collections::HashMap;
14use tonic::async_trait;
15
16/// Core struct representing transfer-related key tweaking data
17#[derive(Debug, Clone)]
18pub struct LeafKeyTweak {
19    /// The leaf node
20    pub leaf: TreeNode,
21
22    /// The public key of the leaf
23    pub old_signing_private_key: SecretKey,
24
25    /// The new public key of the leaf
26    pub new_signing_public_key: PublicKey,
27}
28
29/// Struct to maintain data for refund signing operations
30#[derive(Debug)]
31pub struct LeafRefundSigningData {
32    /// The public key of the leaf
33    pub signing_public_key: PublicKey,
34
35    /// The public key of the receiver
36    pub receiving_pubkey: PublicKey,
37
38    /// The transaction to be signed
39    pub tx: Transaction,
40
41    /// The refund transaction
42    pub refund_tx: Option<Transaction>,
43
44    /// Signing commitment
45    pub commitment: ProtoSigningCommitment,
46
47    /// The vout of the transaction
48    pub vout: u32,
49}
50
51#[async_trait]
52pub(crate) trait TransferInternalHandlers<S: SparkSigner + Send + Sync> {
53    /// Top-level transfer execution function, given the leaves to transfer. The function expects the leaves to be in [`LeafKeyTweak`] format.
54    ///
55    /// # Arguments
56    ///
57    /// * `leaves` - A vector of [`LeafKeyTweak`] objects representing the leaves to transfer.
58    /// * `receiver_identity_pubkey` - The public key of the receiver.
59    /// * `expiry_time` - The expiry time of the transfer.
60    ///
61    /// # Returns
62    ///
63    /// A [`Transfer`] object representing the transfer. This is an auto-converted protobuf object that is returned by the Spark API as the last step of the transfer for the sender.
64    async fn start_send_transfer(
65        &self,
66        leaves: &Vec<LeafKeyTweak>,
67        receiver_identity_pubkey: &PublicKey,
68        expiry_time: u64,
69    ) -> Result<Transfer, SparkSdkError>;
70
71    async fn send_transfer_tweak_key(
72        &self,
73        transfer: Transfer,
74        leaves: &Vec<LeafKeyTweak>,
75        refund_signature_map: &HashMap<String, Vec<u8>>,
76    ) -> Result<Transfer, SparkSdkError>;
77
78    async fn send_transfer_sign_refunds(
79        &self,
80        leaves: &Vec<LeafKeyTweak>,
81        receiver_identity_pubkey: &PublicKey,
82        expiry_time: u64,
83    ) -> Result<(Transfer, HashMap<String, Vec<u8>>), SparkSdkError>;
84
85    fn prepare_send_transfer_key_tweaks(
86        &self,
87        transfer: &Transfer,
88        leaves: &Vec<LeafKeyTweak>,
89        refund_signature_map: &HashMap<String, Vec<u8>>,
90    ) -> Result<HashMap<String, Vec<SendLeafKeyTweak>>, SparkSdkError>;
91
92    fn prepare_single_send_transfer_key_tweak(
93        &self,
94        transfer_id: &str,
95        leaf: &LeafKeyTweak,
96        receiver_pubkey: &PublicKey,
97        refund_signature: Option<Vec<u8>>,
98    ) -> Result<HashMap<String, SendLeafKeyTweak>, SparkSdkError>;
99
100    fn prepare_refund_so_signing_jobs(
101        &self,
102        leaves: &Vec<LeafKeyTweak>,
103        leaf_data_map: &mut HashMap<String, LeafRefundSigningData>,
104    ) -> Result<Vec<LeafRefundTxSigningJob>, SparkSdkError>;
105
106    fn create_refund_tx(
107        &self,
108        leaf: &TreeNode,
109        receiving_pubkey: &PublicKey,
110    ) -> Result<bitcoin::Transaction, SparkSdkError>;
111
112    // Helper methods
113    fn compare_transfers(&self, t1: &Transfer, t2: &Transfer) -> bool;
114
115    async fn claim_finalize_incoming_transfer(
116        &self,
117        transfer: &Transfer,
118        leaves: &Vec<LeafKeyTweak>,
119    ) -> Result<(), SparkSdkError>;
120
121    async fn claim_transfer_tweak_keys(
122        &self,
123        transfer: &Transfer,
124        leaves: &Vec<LeafKeyTweak>,
125    ) -> Result<(), SparkSdkError>;
126
127    fn prepare_claim_leaves_key_tweaks(
128        &self,
129        leaves: &Vec<LeafKeyTweak>,
130    ) -> Result<HashMap<String, Vec<ClaimLeafKeyTweak>>, SparkSdkError>;
131
132    fn prepare_claim_leaf_key_tweaks(
133        &self,
134        leaf: &LeafKeyTweak,
135    ) -> Result<HashMap<String, ClaimLeafKeyTweak>, SparkSdkError>;
136
137    async fn claim_transfer_sign_refunds(
138        &self,
139        transfer: &Transfer,
140        leaf_keys: &Vec<LeafKeyTweak>,
141    ) -> Result<Vec<spark_protos::spark::NodeSignatures>, SparkSdkError>;
142
143    async fn finalize_transfer(
144        &self,
145        signatures: &[spark_protos::spark::NodeSignatures],
146    ) -> Result<(), SparkSdkError>;
147
148    /// Verifies a pending transfer sent by a remote party. This will:
149    ///   1) Parse and verify the ECDSA signature from the sender.
150    ///   2) Decrypt the leaf secrets for all leaves using our own identity private key.
151    ///
152    /// # Arguments
153    ///
154    /// * `transfer` - The transfer object to verify.
155    ///
156    /// # Returns
157    ///
158    /// A `HashMap` of leaf IDs to the decrypted private keys for each leaf.
159    async fn verify_pending_transfer(
160        &self,
161        transfer: &spark_protos::spark::Transfer,
162    ) -> Result<HashMap<String, SecretKey>, SparkSdkError>;
163
164    async fn query_all_transfers(
165        &self,
166        limit: u32,
167        offset: u32,
168    ) -> Result<QueryAllTransfersResponse, SparkSdkError>;
169
170    /// Cancels a transfer from all Spark operators.
171    async fn cancel_send_transfer(
172        &self,
173        transfer_id: String,
174    ) -> Result<Option<Transfer>, SparkSdkError>;
175}