Skip to main content

smplx_sdk/transaction/
partial_input.rs

1use simplicityhl::elements::confidential::{Asset, Value};
2use simplicityhl::elements::pset::Input;
3use simplicityhl::elements::{AssetId, LockTime, OutPoint, Sequence, TxOut, TxOutSecrets, Txid};
4
5use crate::program::ProgramTrait;
6use crate::program::WitnessTrait;
7
8use super::UTXO;
9
10/// Defines the type of signature required for an input.
11#[derive(Debug, Clone)]
12pub enum RequiredSignature {
13    /// No signature is required.
14    None,
15    /// A standard Native ECDSA (WPKH) signature is required.
16    NativeEcdsa,
17    /// A generic witness payload associated with an external name.
18    Witness(String),
19    /// A witness payload requiring traversal through a specified path hierarchy.
20    WitnessWithPath(String, Vec<String>),
21}
22
23impl RequiredSignature {
24    /// Creates a `WitnessWithPath` requirement using an iterator of path segments.
25    pub fn witness_with_path<I>(name: &str, path: I) -> Self
26    where
27        I: IntoIterator,
28        I::Item: AsRef<str>,
29    {
30        RequiredSignature::WitnessWithPath(
31            name.to_string(),
32            path.into_iter().map(|s| s.as_ref().to_string()).collect(),
33        )
34    }
35}
36
37/// Represents partially prepared input data for Elements transactions.
38#[derive(Debug, Clone)]
39pub struct PartialInput {
40    /// The transaction ID containing the target UTXO being spent.
41    pub witness_txid: Txid,
42    /// The output index of the UTXO within the transaction being spent.
43    pub witness_output_index: u32,
44    /// The native transaction output corresponding to the targeted UTXO.
45    pub witness_utxo: TxOut,
46    /// The sequence number indicating transaction replaceability or relative timelocking.
47    pub sequence: Sequence,
48    /// Absolute timelock criteria enforced against the input.
49    pub locktime: LockTime,
50    /// The explicit amount value in Satoshis for the input, if available.
51    /// Note: if UTXO is explicit, `amount` and `asset` are `Some`.
52    pub amount: Option<u64>,
53    /// The explicit `AssetId` being spent by the input, if available.
54    pub asset: Option<AssetId>,
55    /// Optional blinding secrets mapping values and asset states into confidential outputs.
56    /// Note: if UTXO is confidential, `secrets` are `Some`.
57    pub secrets: Option<TxOutSecrets>,
58}
59
60/// Represents an input that runs a specific Simplicity program with an associated witness.
61#[derive(Clone)]
62pub struct ProgramInput {
63    /// The compiled program interface associated with the input.
64    pub program: Box<dyn ProgramTrait>,
65    /// The witness values required to satisfy the program.
66    pub witness: Box<dyn WitnessTrait>,
67}
68
69/// Represents an input designated for asset issuance or reissuance.
70#[derive(Clone, Debug)]
71pub enum IssuanceInput {
72    /// Represents a completely new asset issuance.
73    Issuance {
74        /// The initial issuance amount for the asset.
75        issuance_amount: u64,
76        /// The initial issuance amount for the inflation key.
77        inflation_amount: u64,
78        /// The contract hash or entropy used to derive the generated `AssetId`.
79        asset_entropy: [u8; 32],
80    },
81    /// Represents a reissuance of an existing asset.
82    Reissuance {
83        /// The amount of the generated asset to issue.
84        issuance_amount: u64,
85        /// The original asset's entropy used to tie this reissuance back to the parent issuance.
86        asset_entropy: [u8; 32],
87    },
88}
89
90impl PartialInput {
91    /// Creates a new `PartialInput` from an existing `UTXO`.
92    /// Extracts explicit value and asset amounts if available.
93    #[must_use]
94    pub fn new(utxo: UTXO) -> Self {
95        let amount = match utxo.txout.value {
96            Value::Explicit(value) => Some(value),
97            _ => None,
98        };
99        let asset = match utxo.txout.asset {
100            Asset::Explicit(asset) => Some(asset),
101            _ => None,
102        };
103
104        Self {
105            witness_txid: utxo.outpoint.txid,
106            witness_output_index: utxo.outpoint.vout,
107            witness_utxo: utxo.txout,
108            sequence: Sequence::default(),
109            locktime: LockTime::ZERO,
110            amount,
111            asset,
112            secrets: utxo.secrets,
113        }
114    }
115
116    /// Sets a specific `Sequence` for the input.
117    #[must_use]
118    pub fn with_sequence(mut self, sequence: Sequence) -> Self {
119        self.sequence = sequence;
120
121        self
122    }
123
124    /// Sets a specific `LockTime` for the input.
125    #[must_use]
126    pub fn with_locktime(mut self, locktime: LockTime) -> Self {
127        self.locktime = locktime;
128
129        self
130    }
131
132    /// Returns the `OutPoint` corresponding to this input.
133    #[must_use]
134    pub fn outpoint(&self) -> OutPoint {
135        OutPoint {
136            txid: self.witness_txid,
137            vout: self.witness_output_index,
138        }
139    }
140
141    /// Converts this `PartialInput` into a fully formed PSET `Input`.
142    #[must_use]
143    pub fn to_input(&self) -> Input {
144        let time_locktime = match self.locktime {
145            LockTime::Seconds(value) => Some(value),
146            LockTime::Blocks(_) => None,
147        };
148        // zero height locktime is essentially ignored
149        let height_locktime = match self.locktime {
150            LockTime::Blocks(value) => Some(value),
151            LockTime::Seconds(_) => None,
152        };
153
154        Input {
155            previous_txid: self.witness_txid,
156            previous_output_index: self.witness_output_index,
157            witness_utxo: Some(self.witness_utxo.clone()),
158            sequence: Some(self.sequence),
159            required_time_locktime: time_locktime,
160            required_height_locktime: height_locktime,
161            amount: self.amount,
162            asset: self.asset,
163            ..Default::default()
164        }
165    }
166}
167
168impl ProgramInput {
169    /// Creates a new `ProgramInput` from a `ProgramTrait` and its associated `WitnessTrait`.
170    #[must_use]
171    pub fn new(program: Box<dyn ProgramTrait>, witness: Box<dyn WitnessTrait>) -> Self {
172        Self { program, witness }
173    }
174}
175
176impl IssuanceInput {
177    /// Creates a new `IssuanceInput` for creating a new asset issuance.
178    #[must_use]
179    pub fn new_issuance(issuance_amount: u64, inflation_amount: u64, asset_entropy: [u8; 32]) -> Self {
180        Self::Issuance {
181            issuance_amount,
182            inflation_amount,
183            asset_entropy,
184        }
185    }
186
187    /// Creates a new `IssuanceInput` for reissuing an existing asset.
188    #[must_use]
189    pub fn new_reissuance(issuance_amount: u64, asset_entropy: [u8; 32]) -> Self {
190        Self::Reissuance {
191            issuance_amount,
192            asset_entropy,
193        }
194    }
195
196    /// Converts this `IssuanceInput` into a partial PSET `Input` configured for issuance or reissuance.
197    #[must_use]
198    pub fn to_input(&self) -> Input {
199        let (issuance_amount, asset_entropy, inflation_amount) = match self {
200            Self::Issuance {
201                issuance_amount,
202                inflation_amount,
203                asset_entropy,
204            } => {
205                let inflation_amount = (*inflation_amount > 0).then_some(*inflation_amount);
206
207                (*issuance_amount, *asset_entropy, inflation_amount)
208            }
209            Self::Reissuance {
210                issuance_amount,
211                asset_entropy,
212            } => (*issuance_amount, *asset_entropy, None),
213        };
214
215        Input {
216            issuance_value_amount: Some(issuance_amount),
217            issuance_asset_entropy: Some(asset_entropy),
218            issuance_inflation_keys: inflation_amount,
219            blinded_issuance: Some(0x00),
220            ..Default::default()
221        }
222    }
223}