1use crate::types::OrchardStoredBundle;
8use serde::{Deserialize, Serialize};
9use sha2::{Digest, Sha256};
10use thiserror::Error;
11
12#[derive(Debug, Clone)]
14pub struct BtcDepositConfigV1 {
15 pub btc_deposit_address: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ShieldIntentV1 {
22 pub protocol_version: u32,
23 pub btc_deposit_address: String,
24 pub amount_sats: u64,
25 pub bundle_sha256_hex: String,
27 pub orchard_cmx_hex: String,
29 pub operator_reference: Option<String>,
31 #[serde(default)]
33 pub btc_txid: Option<String>,
34}
35
36#[derive(Debug, Error)]
37pub enum BridgeError {
38 #[error("stored bundle must contain at least one action")]
39 NoActions,
40}
41
42pub fn bundle_content_sha256(bundle: &OrchardStoredBundle) -> [u8; 32] {
44 let bytes = serde_json::to_vec(bundle).expect("OrchardStoredBundle serializes");
45 Sha256::digest(bytes).into()
46}
47
48pub fn build_shield_intent_v1(
50 bundle: &OrchardStoredBundle,
51 cfg: &BtcDepositConfigV1,
52 amount_sats: u64,
53 operator_reference: Option<String>,
54 btc_txid: Option<String>,
55) -> Result<ShieldIntentV1, BridgeError> {
56 let action = bundle.actions.first().ok_or(BridgeError::NoActions)?;
57 Ok(ShieldIntentV1 {
58 protocol_version: 1,
59 btc_deposit_address: cfg.btc_deposit_address.clone(),
60 amount_sats,
61 bundle_sha256_hex: hex::encode(bundle_content_sha256(bundle)),
62 orchard_cmx_hex: hex::encode(action.cmx),
63 operator_reference,
64 btc_txid,
65 })
66}