Skip to main content

breez_sdk_spark/signer/
external_spark_adapter.rs

1//! Adapter from a foreign [`ExternalSparkSigner`] to a native
2//! `spark_wallet::SparkSigner`.
3//!
4//! Converts each native request into its FFI mirror, calls the foreign signer,
5//! and converts the FFI response back into the native type.
6
7use std::sync::Arc;
8
9use bitcoin::secp256k1::{PublicKey, ecdsa, schnorr};
10use spark_wallet::{
11    FrostJob, FrostShareResult, PrepareClaimRequest, PrepareLightningReceiveRequest,
12    PrepareStaticDepositClaimRequest, PrepareStaticDepositRequest, PrepareTokenTransactionRequest,
13    PrepareTransferRequest, PreparedClaim, PreparedLightningReceive, PreparedStaticDeposit,
14    PreparedStaticDepositClaim, PreparedTokenTransaction, PreparedTransfer,
15    SignSparkInvoiceRequest, SignStaticDepositRefundRequest, SignedSparkInvoice, SignerError,
16    StartStaticDepositRefundRequest, StartedStaticDepositRefund, TreeNodeId,
17};
18
19use super::ExternalSparkSigner;
20use super::external_spark_types::{
21    ExternalFrostJob, ExternalFrostShareResult, ExternalPrepareClaimRequest,
22    ExternalPrepareLightningReceiveRequest, ExternalPrepareStaticDepositClaimRequest,
23    ExternalPrepareStaticDepositRequest, ExternalPrepareTokenTransactionRequest,
24    ExternalPrepareTransferRequest, ExternalSignSparkInvoiceRequest,
25    ExternalSignStaticDepositRefundRequest, ExternalStartStaticDepositRefundRequest,
26};
27use super::external_types::ExternalTreeNodeId;
28
29/// Wraps a foreign [`ExternalSparkSigner`] and implements the native
30/// `spark_wallet::SparkSigner` over it.
31pub struct ExternalSparkSignerAdapter {
32    inner: Arc<dyn ExternalSparkSigner>,
33}
34
35impl ExternalSparkSignerAdapter {
36    pub fn new(inner: Arc<dyn ExternalSparkSigner>) -> Self {
37        Self { inner }
38    }
39}
40
41fn to_spark_err<E: std::fmt::Display>(e: E) -> SignerError {
42    SignerError::Generic(e.to_string())
43}
44
45#[macros::async_trait]
46impl spark_wallet::SparkSigner for ExternalSparkSignerAdapter {
47    async fn get_identity_public_key(&self) -> Result<PublicKey, SignerError> {
48        self.inner
49            .get_identity_public_key()
50            .await
51            .map_err(to_spark_err)?
52            .to_public_key()
53            .map_err(to_spark_err)
54    }
55
56    async fn get_public_key_for_leaf(
57        &self,
58        leaf_id: &TreeNodeId,
59    ) -> Result<PublicKey, SignerError> {
60        let ext = ExternalTreeNodeId::from_tree_node_id(leaf_id).map_err(to_spark_err)?;
61        self.inner
62            .get_public_key_for_leaf(ext)
63            .await
64            .map_err(to_spark_err)?
65            .to_public_key()
66            .map_err(to_spark_err)
67    }
68
69    fn is_remote(&self) -> bool {
70        self.inner.is_remote()
71    }
72
73    async fn get_static_deposit_public_key(&self, index: u32) -> Result<PublicKey, SignerError> {
74        self.inner
75            .get_static_deposit_public_key(index)
76            .await
77            .map_err(to_spark_err)?
78            .to_public_key()
79            .map_err(to_spark_err)
80    }
81
82    async fn sign_authentication_challenge(
83        &self,
84        challenge: &[u8],
85    ) -> Result<ecdsa::Signature, SignerError> {
86        self.inner
87            .sign_authentication_challenge(challenge.to_vec())
88            .await
89            .map_err(to_spark_err)?
90            .to_signature()
91            .map_err(to_spark_err)
92    }
93
94    async fn sign_message(&self, message: &[u8]) -> Result<ecdsa::Signature, SignerError> {
95        self.inner
96            .sign_message(message.to_vec())
97            .await
98            .map_err(to_spark_err)?
99            .to_signature()
100            .map_err(to_spark_err)
101    }
102
103    async fn sign_leaf_refund_spend(
104        &self,
105        leaf_id: &TreeNodeId,
106        sighash: &[u8],
107    ) -> Result<schnorr::Signature, SignerError> {
108        let ext = ExternalTreeNodeId::from_tree_node_id(leaf_id).map_err(to_spark_err)?;
109        self.inner
110            .sign_leaf_refund_spend(ext, sighash.to_vec())
111            .await
112            .map_err(to_spark_err)?
113            .to_signature()
114            .map_err(to_spark_err)
115    }
116
117    async fn sign_frost(&self, jobs: Vec<FrostJob>) -> Result<Vec<FrostShareResult>, SignerError> {
118        let ext_jobs = jobs
119            .iter()
120            .map(ExternalFrostJob::from_frost_job)
121            .collect::<Result<Vec<_>, _>>()
122            .map_err(to_spark_err)?;
123        let results = self
124            .inner
125            .sign_frost(ext_jobs)
126            .await
127            .map_err(to_spark_err)?;
128        results
129            .iter()
130            .map(ExternalFrostShareResult::to_frost_share_result)
131            .collect::<Result<Vec<_>, _>>()
132            .map_err(to_spark_err)
133    }
134
135    async fn prepare_transfer(
136        &self,
137        request: PrepareTransferRequest,
138    ) -> Result<PreparedTransfer, SignerError> {
139        let ext = ExternalPrepareTransferRequest::from_prepare_transfer_request(&request)
140            .map_err(to_spark_err)?;
141        self.inner
142            .prepare_transfer(ext)
143            .await
144            .map_err(to_spark_err)?
145            .to_prepared_transfer()
146            .map_err(to_spark_err)
147    }
148
149    async fn prepare_claim(
150        &self,
151        request: PrepareClaimRequest,
152    ) -> Result<PreparedClaim, SignerError> {
153        let ext = ExternalPrepareClaimRequest::from_prepare_claim_request(&request)
154            .map_err(to_spark_err)?;
155        self.inner
156            .prepare_claim(ext)
157            .await
158            .map_err(to_spark_err)?
159            .to_prepared_claim()
160            .map_err(to_spark_err)
161    }
162
163    async fn prepare_lightning_receive(
164        &self,
165        request: PrepareLightningReceiveRequest,
166    ) -> Result<PreparedLightningReceive, SignerError> {
167        let ext = ExternalPrepareLightningReceiveRequest::from_prepare_lightning_receive_request(
168            &request,
169        )
170        .map_err(to_spark_err)?;
171        self.inner
172            .prepare_lightning_receive(ext)
173            .await
174            .map_err(to_spark_err)?
175            .to_prepared_lightning_receive()
176            .map_err(to_spark_err)
177    }
178
179    async fn prepare_static_deposit(
180        &self,
181        request: PrepareStaticDepositRequest,
182    ) -> Result<PreparedStaticDeposit, SignerError> {
183        let ext =
184            ExternalPrepareStaticDepositRequest::from_prepare_static_deposit_request(&request)
185                .map_err(to_spark_err)?;
186        self.inner
187            .prepare_static_deposit(ext)
188            .await
189            .map_err(to_spark_err)?
190            .to_prepared_static_deposit()
191            .map_err(to_spark_err)
192    }
193
194    async fn start_static_deposit_refund(
195        &self,
196        request: StartStaticDepositRefundRequest,
197    ) -> Result<StartedStaticDepositRefund, SignerError> {
198        let ext =
199            ExternalStartStaticDepositRefundRequest::from_start_static_deposit_refund_request(
200                &request,
201            )
202            .map_err(to_spark_err)?;
203        self.inner
204            .start_static_deposit_refund(ext)
205            .await
206            .map_err(to_spark_err)?
207            .to_started_static_deposit_refund()
208            .map_err(to_spark_err)
209    }
210
211    async fn sign_static_deposit_refund(
212        &self,
213        request: SignStaticDepositRefundRequest,
214    ) -> Result<frost_secp256k1_tr::Signature, SignerError> {
215        let ext = ExternalSignStaticDepositRefundRequest::from_sign_static_deposit_refund_request(
216            &request,
217        )
218        .map_err(to_spark_err)?;
219        self.inner
220            .sign_static_deposit_refund(ext)
221            .await
222            .map_err(to_spark_err)?
223            .to_frost_signature()
224            .map_err(to_spark_err)
225    }
226
227    async fn sign_spark_invoice(
228        &self,
229        request: SignSparkInvoiceRequest,
230    ) -> Result<SignedSparkInvoice, SignerError> {
231        let ext = ExternalSignSparkInvoiceRequest::from_sign_spark_invoice_request(&request)
232            .map_err(to_spark_err)?;
233        self.inner
234            .sign_spark_invoice(ext)
235            .await
236            .map_err(to_spark_err)?
237            .to_signed_spark_invoice()
238            .map_err(to_spark_err)
239    }
240
241    async fn prepare_token_transaction(
242        &self,
243        request: PrepareTokenTransactionRequest,
244    ) -> Result<PreparedTokenTransaction, SignerError> {
245        let ext = ExternalPrepareTokenTransactionRequest::from_prepare_token_transaction_request(
246            &request,
247        )
248        .map_err(to_spark_err)?;
249        self.inner
250            .prepare_token_transaction(ext)
251            .await
252            .map_err(to_spark_err)?
253            .to_prepared_token_transaction()
254            .map_err(to_spark_err)
255    }
256
257    async fn prepare_static_deposit_claim(
258        &self,
259        request: PrepareStaticDepositClaimRequest,
260    ) -> Result<PreparedStaticDepositClaim, SignerError> {
261        let ext =
262            ExternalPrepareStaticDepositClaimRequest::from_prepare_static_deposit_claim_request(
263                &request,
264            )
265            .map_err(to_spark_err)?;
266        self.inner
267            .prepare_static_deposit_claim(ext)
268            .await
269            .map_err(to_spark_err)?
270            .to_prepared_static_deposit_claim()
271            .map_err(to_spark_err)
272    }
273}