ord/subcommand/
list.rs

1use super::*;
2
3#[derive(Debug, Parser)]
4pub(crate) struct List {
5  #[arg(help = "List sats in <OUTPOINT>.")]
6  outpoint: OutPoint,
7}
8
9#[derive(Debug, PartialEq, Serialize, Deserialize)]
10pub struct Output {
11  pub ranges: Option<Vec<Range>>,
12  pub spent: bool,
13}
14
15#[derive(Debug, PartialEq, Serialize, Deserialize)]
16pub struct Range {
17  pub end: u64,
18  pub name: String,
19  pub offset: u64,
20  pub rarity: Rarity,
21  pub size: u64,
22  pub start: u64,
23}
24
25impl List {
26  pub(crate) fn run(self, settings: Settings) -> SubcommandResult {
27    let index = Index::open(&settings)?;
28
29    if !index.has_sat_index() {
30      bail!("list requires index created with `--index-sats` flag");
31    }
32
33    index.update()?;
34
35    ensure! {
36      index.is_output_in_active_chain(self.outpoint)?,
37      "output not found"
38    }
39
40    let ranges = index.list(self.outpoint)?;
41
42    let spent = index.is_output_spent(self.outpoint)?;
43
44    Ok(Some(Box::new(Output {
45      spent,
46      ranges: ranges.map(output_ranges),
47    })))
48  }
49}
50
51fn output_ranges(ranges: Vec<(u64, u64)>) -> Vec<Range> {
52  let mut offset = 0;
53  ranges
54    .into_iter()
55    .map(|(start, end)| {
56      let size = end - start;
57      let output = Range {
58        end,
59        name: Sat(start).name(),
60        offset,
61        rarity: Sat(start).rarity(),
62        size,
63        start,
64      };
65
66      offset += size;
67
68      output
69    })
70    .collect()
71}
72
73#[cfg(test)]
74mod tests {
75  use super::*;
76
77  #[test]
78  fn list_ranges() {
79    assert_eq!(
80      output_ranges(vec![
81        (50 * COIN_VALUE, 55 * COIN_VALUE),
82        (10, 100),
83        (1050000000000000, 1150000000000000),
84      ]),
85      vec![
86        Range {
87          end: 55 * COIN_VALUE,
88          name: "nvtcsezkbth".to_string(),
89          offset: 0,
90          rarity: Rarity::Uncommon,
91          size: 5 * COIN_VALUE,
92          start: 50 * COIN_VALUE,
93        },
94        Range {
95          end: 100,
96          name: "nvtdijuwxlf".to_string(),
97          offset: 5 * COIN_VALUE,
98          rarity: Rarity::Common,
99          size: 90,
100          start: 10,
101        },
102        Range {
103          end: 1150000000000000,
104          name: "gkjbdrhkfqf".to_string(),
105          offset: 5 * COIN_VALUE + 90,
106          rarity: Rarity::Epic,
107          size: 100000000000000,
108          start: 1050000000000000,
109        }
110      ]
111    )
112  }
113}