tx3_resolver/inputs/
canonical.rs1use std::collections::HashSet;
4
5use tx3_tir::model::v1beta0 as tir;
6use tx3_tir::model::{assets::CanonicalAssets, core::UtxoRef};
7
8use crate::Error;
9
10macro_rules! data_or_bail {
11 ($expr:expr, bytes) => {
12 $expr
13 .as_bytes()
14 .ok_or(Error::ExpectedData("bytes".to_string(), $expr.clone()))
15 };
16
17 ($expr:expr, number) => {
18 $expr
19 .as_number()
20 .ok_or(Error::ExpectedData("number".to_string(), $expr.clone()))?
21 };
22
23 ($expr:expr, assets) => {
24 $expr
25 .as_assets()
26 .ok_or(Error::ExpectedData("assets".to_string(), $expr.clone()))
27 };
28
29 ($expr:expr, utxo_refs) => {
30 $expr
31 .as_utxo_refs()
32 .ok_or(Error::ExpectedData("utxo refs".to_string(), $expr.clone()))
33 };
34}
35
36#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
37pub struct CanonicalQuery {
38 pub address: Option<Vec<u8>>,
39 pub min_amount: Option<CanonicalAssets>,
40 pub refs: HashSet<UtxoRef>,
41 pub support_many: bool,
42 pub collateral: bool,
43}
44
45impl std::fmt::Display for CanonicalQuery {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "CanonicalQuery {{")?;
48
49 if let Some(address) = &self.address {
50 write!(f, "address: {}", hex::encode(address))?;
51 }
52
53 if let Some(min_amount) = &self.min_amount {
54 write!(f, "min_amount: {}", min_amount)?;
55 }
56
57 for (i, ref_) in self.refs.iter().enumerate() {
58 write!(f, "ref[{}]:{}#{}", i, hex::encode(&ref_.txid), ref_.index)?;
59 }
60
61 write!(f, "support_many: {:?}", self.support_many)?;
62 write!(f, "for_collateral: {:?}", self.collateral)?;
63 write!(f, "}}")
64 }
65}
66
67impl TryFrom<tir::InputQuery> for CanonicalQuery {
68 type Error = Error;
69
70 fn try_from(query: tir::InputQuery) -> Result<Self, Self::Error> {
71 let address = query
72 .address
73 .as_option()
74 .map(|x| data_or_bail!(x, bytes))
75 .transpose()?
76 .map(Vec::from);
77
78 let min_amount = query
79 .min_amount
80 .as_option()
81 .map(|x| data_or_bail!(x, assets))
82 .transpose()?
83 .map(|x| CanonicalAssets::from(Vec::from(x)));
84
85 let refs = query
86 .r#ref
87 .as_option()
88 .map(|x| data_or_bail!(x, utxo_refs))
89 .transpose()?
90 .map(|x| HashSet::from_iter(x.iter().cloned()))
91 .unwrap_or_default();
92
93 Ok(Self {
94 address,
95 min_amount,
96 refs,
97 support_many: query.many,
98 collateral: query.collateral,
99 })
100 }
101}