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}