ord/subcommand/wallet/
balance.rs1use super::*;
2
3#[derive(Serialize, Deserialize, Debug, PartialEq)]
4pub struct Output {
5 pub cardinal: u64,
6 pub ordinal: u64,
7 #[serde(default, skip_serializing_if = "Option::is_none")]
8 pub runes: Option<BTreeMap<SpacedRune, Decimal>>,
9 #[serde(default, skip_serializing_if = "Option::is_none")]
10 pub runic: Option<u64>,
11 pub total: u64,
12}
13
14pub(crate) fn run(wallet: Wallet) -> SubcommandResult {
15 let unspent_outputs = wallet.utxos();
16
17 let inscription_outputs = wallet
18 .inscriptions()
19 .keys()
20 .map(|satpoint| satpoint.outpoint)
21 .collect::<BTreeSet<OutPoint>>();
22
23 let mut cardinal = 0;
24 let mut ordinal = 0;
25 let mut runes = BTreeMap::new();
26 let mut runic = 0;
27
28 for (output, txout) in unspent_outputs {
29 let rune_balances = wallet.get_runes_balances_for_output(output)?;
30
31 let is_ordinal = inscription_outputs.contains(output);
32 let is_runic = !rune_balances.is_empty();
33
34 if is_ordinal {
35 ordinal += txout.value;
36 }
37
38 if is_runic {
39 for (spaced_rune, pile) in rune_balances {
40 runes
41 .entry(spaced_rune)
42 .and_modify(|decimal: &mut Decimal| {
43 assert_eq!(decimal.scale, pile.divisibility);
44 decimal.value += pile.amount;
45 })
46 .or_insert(Decimal {
47 value: pile.amount,
48 scale: pile.divisibility,
49 });
50 }
51 runic += txout.value;
52 }
53
54 if !is_ordinal && !is_runic {
55 cardinal += txout.value;
56 }
57
58 if is_ordinal && is_runic {
59 eprintln!("warning: output {output} contains both inscriptions and runes");
60 }
61 }
62
63 Ok(Some(Box::new(Output {
64 cardinal,
65 ordinal,
66 runes: wallet.has_rune_index().then_some(runes),
67 runic: wallet.has_rune_index().then_some(runic),
68 total: cardinal + ordinal + runic,
69 })))
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn runes_and_runic_fields_are_not_present_if_none() {
78 assert_eq!(
79 serde_json::to_string(&Output {
80 cardinal: 0,
81 ordinal: 0,
82 runes: None,
83 runic: None,
84 total: 0
85 })
86 .unwrap(),
87 r#"{"cardinal":0,"ordinal":0,"total":0}"#
88 );
89 }
90}