1use bitcoin::bip32::DerivationPath;
6use bitcoin::secp256k1;
7use serde::{Deserialize, Serialize};
8use std::str::FromStr;
9
10use crate::SdkError;
11
12#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
14#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
15pub struct PublicKeyBytes {
16 pub bytes: Vec<u8>,
17}
18
19impl PublicKeyBytes {
20 pub fn from_public_key(pk: &secp256k1::PublicKey) -> Self {
21 Self {
22 bytes: pk.serialize().to_vec(),
23 }
24 }
25
26 pub fn to_public_key(&self) -> Result<secp256k1::PublicKey, SdkError> {
27 secp256k1::PublicKey::from_slice(&self.bytes)
28 .map_err(|e| SdkError::Generic(format!("Invalid public key bytes: {e}")))
29 }
30}
31
32#[derive(Clone, Debug, Serialize, Deserialize)]
34#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
35pub struct EcdsaSignatureBytes {
36 pub bytes: Vec<u8>,
37}
38
39impl EcdsaSignatureBytes {
40 pub fn from_signature(sig: &secp256k1::ecdsa::Signature) -> Self {
41 Self {
42 bytes: sig.serialize_compact().to_vec(),
43 }
44 }
45
46 pub fn to_signature(&self) -> Result<secp256k1::ecdsa::Signature, SdkError> {
47 secp256k1::ecdsa::Signature::from_compact(&self.bytes)
48 .map_err(|e| SdkError::Generic(format!("Invalid ECDSA signature bytes: {e}")))
49 }
50}
51
52#[derive(Clone, Debug, Serialize, Deserialize)]
54#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
55pub struct SchnorrSignatureBytes {
56 pub bytes: Vec<u8>,
57}
58
59impl SchnorrSignatureBytes {
60 pub fn from_signature(sig: &secp256k1::schnorr::Signature) -> Self {
61 Self {
62 bytes: sig.as_ref().to_vec(),
63 }
64 }
65
66 pub fn to_signature(&self) -> Result<secp256k1::schnorr::Signature, SdkError> {
67 secp256k1::schnorr::Signature::from_slice(&self.bytes)
68 .map_err(|e| SdkError::Generic(format!("Invalid Schnorr signature bytes: {e}")))
69 }
70}
71
72#[derive(Clone, Debug, Serialize, Deserialize)]
74#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
75pub struct RecoverableEcdsaSignatureBytes {
76 pub bytes: Vec<u8>,
77}
78
79impl RecoverableEcdsaSignatureBytes {
80 pub fn new(bytes: Vec<u8>) -> Self {
81 Self { bytes }
82 }
83}
84
85#[derive(Clone, Debug, Serialize, Deserialize)]
87#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
88pub struct PrivateKeyBytes {
89 pub bytes: Vec<u8>,
90}
91
92impl PrivateKeyBytes {
93 pub fn from_secret_key(sk: &secp256k1::SecretKey) -> Self {
94 Self {
95 bytes: sk.secret_bytes().to_vec(),
96 }
97 }
98
99 pub fn to_secret_key(&self) -> Result<secp256k1::SecretKey, SdkError> {
100 secp256k1::SecretKey::from_slice(&self.bytes)
101 .map_err(|e| SdkError::Generic(format!("Invalid private key bytes: {e}")))
102 }
103}
104
105pub fn derivation_path_to_string(path: &DerivationPath) -> String {
107 path.to_string()
108}
109
110pub fn string_to_derivation_path(s: &str) -> Result<DerivationPath, SdkError> {
111 DerivationPath::from_str(s)
112 .map_err(|e| SdkError::Generic(format!("Invalid derivation path '{s}': {e}")))
113}
114
115#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
117#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
118pub struct ExternalTreeNodeId {
119 pub id: String,
121}
122
123impl ExternalTreeNodeId {
124 pub fn from_tree_node_id(id: &spark_wallet::TreeNodeId) -> Result<Self, SdkError> {
125 Ok(Self { id: id.to_string() })
126 }
127
128 pub fn to_tree_node_id(&self) -> Result<spark_wallet::TreeNodeId, SdkError> {
129 spark_wallet::TreeNodeId::from_str(&self.id)
130 .map_err(|e| SdkError::Generic(format!("Invalid TreeNodeId: {e}")))
131 }
132}
133
134#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
136#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
137pub struct ExternalEncryptedPrivateKey {
138 pub ciphertext: Vec<u8>,
140}
141
142impl ExternalEncryptedPrivateKey {
143 pub fn from_encrypted_private_key(
144 key: &spark_wallet::EncryptedPrivateKey,
145 ) -> Result<Self, SdkError> {
146 Ok(Self {
147 ciphertext: key.as_slice().to_vec(),
148 })
149 }
150
151 pub fn to_encrypted_private_key(&self) -> Result<spark_wallet::EncryptedPrivateKey, SdkError> {
152 Ok(spark_wallet::EncryptedPrivateKey::new(
153 self.ciphertext.clone(),
154 ))
155 }
156}
157
158#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
160#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
161pub enum ExternalPrivateKeySource {
162 Derived { node_id: ExternalTreeNodeId },
164 Encrypted { key: ExternalEncryptedPrivateKey },
166}
167
168impl ExternalPrivateKeySource {
169 pub fn from_private_key_source(
170 source: &spark_wallet::PrivateKeySource,
171 ) -> Result<Self, SdkError> {
172 match source {
173 spark_wallet::PrivateKeySource::Derived(node_id) => Ok(Self::Derived {
174 node_id: ExternalTreeNodeId::from_tree_node_id(node_id)?,
175 }),
176 spark_wallet::PrivateKeySource::Encrypted(key) => Ok(Self::Encrypted {
177 key: ExternalEncryptedPrivateKey::from_encrypted_private_key(key)?,
178 }),
179 }
180 }
181
182 pub fn to_private_key_source(&self) -> Result<spark_wallet::PrivateKeySource, SdkError> {
183 match self {
184 Self::Derived { node_id } => Ok(spark_wallet::PrivateKeySource::Derived(
185 node_id.to_tree_node_id()?,
186 )),
187 Self::Encrypted { key } => Ok(spark_wallet::PrivateKeySource::Encrypted(
188 key.to_encrypted_private_key()?,
189 )),
190 }
191 }
192}
193
194#[derive(Clone, Debug, Serialize, Deserialize)]
196#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
197pub enum ExternalSecretToSplit {
198 PrivateKey { source: ExternalPrivateKeySource },
200 Preimage { data: Vec<u8> },
202}
203
204impl ExternalSecretToSplit {
205 pub fn from_secret_to_split(secret: &spark_wallet::SecretToSplit) -> Result<Self, SdkError> {
206 match secret {
207 spark_wallet::SecretToSplit::PrivateKey(source) => Ok(Self::PrivateKey {
208 source: ExternalPrivateKeySource::from_private_key_source(source)?,
209 }),
210 spark_wallet::SecretToSplit::Preimage(data) => {
211 Ok(Self::Preimage { data: data.clone() })
212 }
213 }
214 }
215
216 pub fn to_secret_to_split(&self) -> Result<spark_wallet::SecretToSplit, SdkError> {
217 match self {
218 Self::PrivateKey { source } => Ok(spark_wallet::SecretToSplit::PrivateKey(
219 source.to_private_key_source()?,
220 )),
221 Self::Preimage { data } => Ok(spark_wallet::SecretToSplit::Preimage(data.clone())),
222 }
223 }
224}
225
226#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
228#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
229pub struct ExternalScalar {
230 pub bytes: Vec<u8>,
232}
233
234#[derive(Clone, Debug, Serialize, Deserialize)]
236#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
237pub struct ExternalSecretShare {
238 pub threshold: u32,
240 pub index: ExternalScalar,
242 pub share: ExternalScalar,
244}
245
246#[derive(Clone, Debug, Serialize, Deserialize)]
248#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
249pub struct ExternalVerifiableSecretShare {
250 pub secret_share: ExternalSecretShare,
252 pub proofs: Vec<Vec<u8>>,
254}
255
256impl ExternalVerifiableSecretShare {
257 pub fn from_verifiable_secret_share(
258 share: &spark_wallet::VerifiableSecretShare,
259 ) -> Result<Self, SdkError> {
260 use k256::elliptic_curve::sec1::ToEncodedPoint;
261
262 let secret_share = ExternalSecretShare {
263 threshold: share
264 .secret_share
265 .threshold
266 .try_into()
267 .map_err(|_| SdkError::Generic("Threshold value too large".to_string()))?,
268 index: ExternalScalar {
269 bytes: share.secret_share.index.to_bytes().to_vec(),
270 },
271 share: ExternalScalar {
272 bytes: share.secret_share.share.to_bytes().to_vec(),
273 },
274 };
275
276 let proofs = share
277 .proofs
278 .iter()
279 .map(|pk| pk.to_encoded_point(true).as_bytes().to_vec())
280 .collect();
281
282 Ok(Self {
283 secret_share,
284 proofs,
285 })
286 }
287
288 pub fn to_verifiable_secret_share(
289 &self,
290 ) -> Result<spark_wallet::VerifiableSecretShare, SdkError> {
291 use k256::elliptic_curve::PrimeField;
292 use k256::{FieldBytes, PublicKey as k256PublicKey, Scalar};
293
294 let index_bytes: [u8; 32] = self.secret_share.index.bytes[..]
295 .try_into()
296 .map_err(|_| SdkError::Generic("Invalid index scalar length".into()))?;
297 let index = Scalar::from_repr(FieldBytes::clone_from_slice(&index_bytes))
298 .into_option()
299 .ok_or_else(|| SdkError::Generic("Invalid index scalar".into()))?;
300
301 let share_bytes: [u8; 32] = self.secret_share.share.bytes[..]
302 .try_into()
303 .map_err(|_| SdkError::Generic("Invalid share scalar length".into()))?;
304 let share = Scalar::from_repr(FieldBytes::clone_from_slice(&share_bytes))
305 .into_option()
306 .ok_or_else(|| SdkError::Generic("Invalid share scalar".into()))?;
307
308 let proofs: Vec<k256PublicKey> = self
309 .proofs
310 .iter()
311 .map(|bytes| {
312 k256PublicKey::from_sec1_bytes(bytes)
313 .map_err(|e| SdkError::Generic(format!("Invalid proof public key: {e}")))
314 })
315 .collect::<Result<Vec<_>, _>>()?;
316
317 Ok(spark_wallet::VerifiableSecretShare {
318 secret_share: spark_wallet::SecretShare {
319 threshold: self.secret_share.threshold as usize,
320 index,
321 share,
322 },
323 proofs,
324 })
325 }
326}
327
328#[derive(Clone, Debug, Serialize, Deserialize)]
330#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
331pub struct ExternalFrostSignatureShare {
332 pub bytes: Vec<u8>,
334}
335
336impl ExternalFrostSignatureShare {
337 pub fn from_signature_share(
338 share: &frost_secp256k1_tr::round2::SignatureShare,
339 ) -> Result<Self, SdkError> {
340 let bytes = share.serialize();
341 Ok(Self { bytes })
342 }
343
344 pub fn to_signature_share(
345 &self,
346 ) -> Result<frost_secp256k1_tr::round2::SignatureShare, SdkError> {
347 frost_secp256k1_tr::round2::SignatureShare::deserialize(&self.bytes)
348 .map_err(|e| SdkError::Generic(format!("Failed to deserialize SignatureShare: {e}")))
349 }
350}
351
352#[derive(Clone, Debug, Serialize, Deserialize)]
354#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
355pub struct ExternalFrostSignature {
356 pub bytes: Vec<u8>,
358}
359
360impl ExternalFrostSignature {
361 pub fn from_frost_signature(sig: &frost_secp256k1_tr::Signature) -> Result<Self, SdkError> {
362 let bytes = sig
363 .serialize()
364 .map_err(|e| SdkError::Generic(format!("Failed to serialize Frost signature: {e}")))?;
365 let bytes = bytes.clone();
366 Ok(Self { bytes })
367 }
368
369 pub fn to_frost_signature(&self) -> Result<frost_secp256k1_tr::Signature, SdkError> {
370 frost_secp256k1_tr::Signature::deserialize(&self.bytes)
371 .map_err(|e| SdkError::Generic(format!("Failed to deserialize Frost signature: {e}")))
372 }
373}
374
375#[derive(Clone, Debug, Serialize, Deserialize)]
377#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
378pub struct ExternalFrostCommitments {
379 pub hiding_commitment: Vec<u8>,
381 pub binding_commitment: Vec<u8>,
383 pub nonces_ciphertext: Vec<u8>,
385}
386
387impl ExternalFrostCommitments {
388 pub fn from_frost_commitments(
389 commitments: &spark_wallet::FrostSigningCommitmentsWithNonces,
390 ) -> Result<Self, SdkError> {
391 let hiding_commitment = commitments.commitments.hiding().serialize().map_err(|e| {
392 SdkError::Generic(format!("Failed to serialize hiding commitment: {e}"))
393 })?;
394 let binding_commitment = commitments.commitments.binding().serialize().map_err(|e| {
395 SdkError::Generic(format!("Failed to serialize binding commitment: {e}"))
396 })?;
397
398 Ok(Self {
399 hiding_commitment,
400 binding_commitment,
401 nonces_ciphertext: commitments.nonces_ciphertext.clone(),
402 })
403 }
404
405 pub fn to_frost_commitments(
406 &self,
407 ) -> Result<spark_wallet::FrostSigningCommitmentsWithNonces, SdkError> {
408 use frost_secp256k1_tr::round1::{NonceCommitment, SigningCommitments};
409
410 let hiding = NonceCommitment::deserialize(&self.hiding_commitment).map_err(|e| {
411 SdkError::Generic(format!("Failed to deserialize hiding commitment: {e}"))
412 })?;
413 let binding = NonceCommitment::deserialize(&self.binding_commitment).map_err(|e| {
414 SdkError::Generic(format!("Failed to deserialize binding commitment: {e}"))
415 })?;
416
417 let commitments = SigningCommitments::new(hiding, binding);
418
419 Ok(spark_wallet::FrostSigningCommitmentsWithNonces {
420 commitments,
421 nonces_ciphertext: self.nonces_ciphertext.clone(),
422 })
423 }
424}
425
426#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
428#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
429pub struct ExternalIdentifier {
430 pub bytes: Vec<u8>,
432}
433
434impl ExternalIdentifier {
435 pub fn from_identifier(id: &frost_secp256k1_tr::Identifier) -> Self {
436 Self {
437 bytes: id.serialize(),
438 }
439 }
440
441 pub fn to_identifier(&self) -> Result<frost_secp256k1_tr::Identifier, SdkError> {
442 frost_secp256k1_tr::Identifier::deserialize(&self.bytes)
443 .map_err(|e| SdkError::Generic(format!("Invalid identifier: {e}")))
444 }
445}
446
447#[derive(Clone, Debug, Serialize, Deserialize)]
449#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
450pub struct ExternalSigningCommitments {
451 pub hiding: Vec<u8>,
453 pub binding: Vec<u8>,
455}
456
457impl ExternalSigningCommitments {
458 pub fn from_signing_commitments(
459 commitments: &frost_secp256k1_tr::round1::SigningCommitments,
460 ) -> Result<Self, SdkError> {
461 let hiding = commitments.hiding().serialize().map_err(|e| {
462 SdkError::Generic(format!("Failed to serialize hiding commitment: {e}"))
463 })?;
464 let binding = commitments.binding().serialize().map_err(|e| {
465 SdkError::Generic(format!("Failed to serialize binding commitment: {e}"))
466 })?;
467 Ok(Self { hiding, binding })
468 }
469
470 pub fn to_signing_commitments(
471 &self,
472 ) -> Result<frost_secp256k1_tr::round1::SigningCommitments, SdkError> {
473 use frost_secp256k1_tr::round1::NonceCommitment;
474
475 let hiding = NonceCommitment::deserialize(&self.hiding)
476 .map_err(|e| SdkError::Generic(format!("Failed to deserialize hiding: {e}")))?;
477 let binding = NonceCommitment::deserialize(&self.binding)
478 .map_err(|e| SdkError::Generic(format!("Failed to deserialize binding: {e}")))?;
479
480 Ok(frost_secp256k1_tr::round1::SigningCommitments::new(
481 hiding, binding,
482 ))
483 }
484}
485
486#[derive(Clone, Debug, Serialize, Deserialize)]
488#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
489pub struct IdentifierCommitmentPair {
490 pub identifier: ExternalIdentifier,
491 pub commitment: ExternalSigningCommitments,
492}
493
494#[derive(Clone, Debug, Serialize, Deserialize)]
496#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
497pub struct IdentifierSignaturePair {
498 pub identifier: ExternalIdentifier,
499 pub signature: ExternalFrostSignatureShare,
500}
501
502#[derive(Clone, Debug, Serialize, Deserialize)]
504#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
505pub struct IdentifierPublicKeyPair {
506 pub identifier: ExternalIdentifier,
507 pub public_key: Vec<u8>,
508}
509
510#[derive(Clone, Debug, Serialize, Deserialize)]
512#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
513pub struct ExternalSignFrostRequest {
514 pub message: Vec<u8>,
516 pub public_key: Vec<u8>,
518 pub private_key: ExternalPrivateKeySource,
520 pub verifying_key: Vec<u8>,
522 pub self_nonce_commitment: ExternalFrostCommitments,
524 pub statechain_commitments: Vec<IdentifierCommitmentPair>,
526 pub adaptor_public_key: Option<Vec<u8>>,
528}
529
530impl ExternalSignFrostRequest {
531 pub fn from_sign_frost_request(
532 request: &spark_wallet::SignFrostRequest,
533 ) -> Result<Self, SdkError> {
534 let statechain_commitments = request
535 .statechain_commitments
536 .iter()
537 .map(|(id, comm)| {
538 Ok(IdentifierCommitmentPair {
539 identifier: ExternalIdentifier::from_identifier(id),
540 commitment: ExternalSigningCommitments::from_signing_commitments(comm)?,
541 })
542 })
543 .collect::<Result<Vec<_>, SdkError>>()?;
544
545 Ok(Self {
546 message: request.message.to_vec(),
547 public_key: request.public_key.serialize().to_vec(),
548 private_key: ExternalPrivateKeySource::from_private_key_source(request.private_key)?,
549 verifying_key: request.verifying_key.serialize().to_vec(),
550 self_nonce_commitment: ExternalFrostCommitments::from_frost_commitments(
551 request.self_nonce_commitment,
552 )?,
553 statechain_commitments,
554 adaptor_public_key: request.adaptor_public_key.map(|pk| pk.serialize().to_vec()),
555 })
556 }
557
558 pub fn to_sign_frost_request(
559 &self,
560 ) -> Result<spark_wallet::SignFrostRequest<'static>, SdkError> {
561 use std::collections::BTreeMap;
562
563 let public_key = secp256k1::PublicKey::from_slice(&self.public_key)
564 .map_err(|e| SdkError::Generic(format!("Invalid public key: {e}")))?;
565 let verifying_key = secp256k1::PublicKey::from_slice(&self.verifying_key)
566 .map_err(|e| SdkError::Generic(format!("Invalid verifying key: {e}")))?;
567
568 let statechain_commitments: BTreeMap<_, _> = self
569 .statechain_commitments
570 .iter()
571 .map(|pair| {
572 Ok((
573 pair.identifier.to_identifier()?,
574 pair.commitment.to_signing_commitments()?,
575 ))
576 })
577 .collect::<Result<_, SdkError>>()?;
578
579 let adaptor_public_key = self
580 .adaptor_public_key
581 .as_ref()
582 .map(|bytes| {
583 secp256k1::PublicKey::from_slice(bytes)
584 .map_err(|e| SdkError::Generic(format!("Invalid adaptor public key: {e}")))
585 })
586 .transpose()?;
587
588 Ok(spark_wallet::SignFrostRequest {
591 message: Box::leak(self.message.clone().into_boxed_slice()),
592 public_key: Box::leak(Box::new(public_key)),
593 private_key: Box::leak(Box::new(self.private_key.to_private_key_source()?)),
594 verifying_key: Box::leak(Box::new(verifying_key)),
595 self_nonce_commitment: Box::leak(Box::new(
596 self.self_nonce_commitment.to_frost_commitments()?,
597 )),
598 statechain_commitments,
599 adaptor_public_key: adaptor_public_key.map(|pk| Box::leak(Box::new(pk)) as &_),
600 })
601 }
602}
603
604#[derive(Clone, Debug, Serialize, Deserialize)]
606#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
607pub struct ExternalAggregateFrostRequest {
608 pub message: Vec<u8>,
610 pub statechain_signatures: Vec<IdentifierSignaturePair>,
612 pub statechain_public_keys: Vec<IdentifierPublicKeyPair>,
614 pub verifying_key: Vec<u8>,
616 pub statechain_commitments: Vec<IdentifierCommitmentPair>,
618 pub self_commitment: ExternalSigningCommitments,
620 pub public_key: Vec<u8>,
622 pub self_signature: ExternalFrostSignatureShare,
624 pub adaptor_public_key: Option<Vec<u8>>,
626}
627
628impl ExternalAggregateFrostRequest {
629 pub fn from_aggregate_frost_request(
630 request: &spark_wallet::AggregateFrostRequest,
631 ) -> Result<Self, SdkError> {
632 let statechain_signatures = request
633 .statechain_signatures
634 .iter()
635 .map(|(id, share)| {
636 Ok(IdentifierSignaturePair {
637 identifier: ExternalIdentifier::from_identifier(id),
638 signature: ExternalFrostSignatureShare::from_signature_share(share)?,
639 })
640 })
641 .collect::<Result<Vec<_>, SdkError>>()?;
642
643 let statechain_public_keys = request
644 .statechain_public_keys
645 .iter()
646 .map(|(id, pk)| IdentifierPublicKeyPair {
647 identifier: ExternalIdentifier::from_identifier(id),
648 public_key: pk.serialize().to_vec(),
649 })
650 .collect();
651
652 let statechain_commitments = request
653 .statechain_commitments
654 .iter()
655 .map(|(id, comm)| {
656 Ok(IdentifierCommitmentPair {
657 identifier: ExternalIdentifier::from_identifier(id),
658 commitment: ExternalSigningCommitments::from_signing_commitments(comm)?,
659 })
660 })
661 .collect::<Result<Vec<_>, SdkError>>()?;
662
663 Ok(Self {
664 message: request.message.to_vec(),
665 statechain_signatures,
666 statechain_public_keys,
667 verifying_key: request.verifying_key.serialize().to_vec(),
668 statechain_commitments,
669 self_commitment: ExternalSigningCommitments::from_signing_commitments(
670 request.self_commitment,
671 )?,
672 public_key: request.public_key.serialize().to_vec(),
673 self_signature: ExternalFrostSignatureShare::from_signature_share(
674 request.self_signature,
675 )?,
676 adaptor_public_key: request.adaptor_public_key.map(|pk| pk.serialize().to_vec()),
677 })
678 }
679
680 pub fn to_aggregate_frost_request(
681 &self,
682 ) -> Result<spark_wallet::AggregateFrostRequest<'static>, SdkError> {
683 use std::collections::BTreeMap;
684
685 let statechain_signatures: BTreeMap<_, _> = self
686 .statechain_signatures
687 .iter()
688 .map(|pair| {
689 Ok((
690 pair.identifier.to_identifier()?,
691 pair.signature.to_signature_share()?,
692 ))
693 })
694 .collect::<Result<_, SdkError>>()?;
695
696 let statechain_public_keys: BTreeMap<_, _> = self
697 .statechain_public_keys
698 .iter()
699 .map(|pair| {
700 Ok((
701 pair.identifier.to_identifier()?,
702 secp256k1::PublicKey::from_slice(&pair.public_key)
703 .map_err(|e| SdkError::Generic(format!("Invalid public key: {e}")))?,
704 ))
705 })
706 .collect::<Result<_, SdkError>>()?;
707
708 let verifying_key = secp256k1::PublicKey::from_slice(&self.verifying_key)
709 .map_err(|e| SdkError::Generic(format!("Invalid verifying key: {e}")))?;
710
711 let statechain_commitments: BTreeMap<_, _> = self
712 .statechain_commitments
713 .iter()
714 .map(|pair| {
715 Ok((
716 pair.identifier.to_identifier()?,
717 pair.commitment.to_signing_commitments()?,
718 ))
719 })
720 .collect::<Result<_, SdkError>>()?;
721
722 let public_key = secp256k1::PublicKey::from_slice(&self.public_key)
723 .map_err(|e| SdkError::Generic(format!("Invalid public key: {e}")))?;
724
725 let adaptor_public_key = self
726 .adaptor_public_key
727 .as_ref()
728 .map(|bytes| {
729 secp256k1::PublicKey::from_slice(bytes)
730 .map_err(|e| SdkError::Generic(format!("Invalid adaptor public key: {e}")))
731 })
732 .transpose()?;
733
734 Ok(spark_wallet::AggregateFrostRequest {
735 message: Box::leak(self.message.clone().into_boxed_slice()),
736 statechain_signatures,
737 statechain_public_keys,
738 verifying_key: Box::leak(Box::new(verifying_key)),
739 statechain_commitments,
740 self_commitment: Box::leak(Box::new(self.self_commitment.to_signing_commitments()?)),
741 public_key: Box::leak(Box::new(public_key)),
742 self_signature: Box::leak(Box::new(self.self_signature.to_signature_share()?)),
743 adaptor_public_key: adaptor_public_key.map(|pk| Box::leak(Box::new(pk)) as &_),
744 })
745 }
746}