bsv_wasm/transaction/
match_criteria.rs1use crate::{ScriptTemplate, Transaction, TxIn, TxOut};
2
3#[cfg(target_arch = "wasm32")]
4use wasm_bindgen::prelude::*;
5
6#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen)]
7#[derive(Debug, Clone, Default)]
8pub struct MatchCriteria {
9 pub(crate) script_template: Option<ScriptTemplate>,
10 pub(crate) exact_value: Option<u64>,
11 pub(crate) min_value: Option<u64>,
12 pub(crate) max_value: Option<u64>,
13}
14
15#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen)]
16impl MatchCriteria {
17 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(constructor))]
18 pub fn new() -> MatchCriteria {
19 MatchCriteria::default()
20 }
21
22 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = setScriptTemplate))]
23 pub fn set_script_template(&mut self, script_template: &ScriptTemplate) -> MatchCriteria {
24 self.script_template = Some(script_template.clone());
25
26 self.clone()
27 }
28
29 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = setValue))]
30 pub fn set_value(&mut self, value: u64) -> MatchCriteria {
31 self.exact_value = Some(value);
32
33 self.clone()
34 }
35
36 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = setMin))]
37 pub fn set_min(&mut self, min: u64) -> MatchCriteria {
38 self.min_value = Some(min);
39
40 self.clone()
41 }
42
43 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = setMax))]
44 pub fn set_max(&mut self, max: u64) -> MatchCriteria {
45 self.max_value = Some(max);
46
47 self.clone()
48 }
49}
50
51#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen)]
52impl Transaction {
53 fn is_matching_output(txout: &TxOut, criteria: &MatchCriteria) -> bool {
54 if matches!(&criteria.script_template, Some(crit_script) if !txout.script_pub_key.is_match(crit_script)) {
56 return false;
57 }
58
59 if criteria.exact_value.is_some() && criteria.exact_value != Some(txout.value) {
61 return false;
62 }
63
64 if criteria.min_value.is_some() && criteria.min_value > Some(txout.value) {
66 return false;
67 }
68
69 if criteria.max_value.is_some() && criteria.max_value < Some(txout.value) {
71 return false;
72 }
73
74 true
75 }
76
77 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = matchOutput))]
81 pub fn match_output(&self, criteria: &MatchCriteria) -> Option<usize> {
82 self.outputs.iter().enumerate().find_map(|(i, txout)| match Transaction::is_matching_output(txout, criteria) {
83 true => Some(i),
84 false => None,
85 })
86 }
87
88 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = matchOutputs))]
92 pub fn match_outputs(&self, criteria: &MatchCriteria) -> Vec<usize> {
93 let matches = self
94 .outputs
95 .iter()
96 .enumerate()
97 .filter_map(|(i, txout)| match Transaction::is_matching_output(txout, criteria) {
98 true => Some(i),
99 false => None,
100 })
101 .collect();
102
103 matches
104 }
105
106 fn is_matching_input(txin: &TxIn, criteria: &MatchCriteria) -> bool {
107 if matches!(&criteria.script_template, Some(crit_script) if !txin.get_finalised_script().unwrap().is_match(crit_script)) {
109 return false;
110 }
111
112 if criteria.exact_value.is_some() && criteria.exact_value != txin.satoshis {
114 return false;
115 }
116
117 if criteria.min_value.is_some() && criteria.min_value > txin.satoshis {
119 return false;
120 }
121
122 if criteria.max_value.is_some() && criteria.max_value < txin.satoshis {
124 return false;
125 }
126
127 true
128 }
129
130 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = matchInput))]
134 pub fn match_input(&self, criteria: &MatchCriteria) -> Option<usize> {
135 self.inputs.iter().enumerate().find_map(|(i, txin)| match Transaction::is_matching_input(txin, criteria) {
136 true => Some(i),
137 false => None,
138 })
139 }
140
141 #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-transaction"), wasm_bindgen(js_name = matchInputs))]
145 pub fn match_inputs(&self, criteria: &MatchCriteria) -> Vec<usize> {
146 let matches = self
147 .inputs
148 .iter()
149 .enumerate()
150 .filter_map(|(i, txin)| match Transaction::is_matching_input(txin, criteria) {
151 true => Some(i),
152 false => None,
153 })
154 .collect();
155
156 matches
157 }
158}