dusk_node_data/events/
transactions.rs1use std::collections::HashMap;
8
9use dusk_core::transfer::RefundAddress;
10
11use super::*;
12use crate::ledger::{Hash, SpentTransaction, Transaction};
13
14#[derive(Clone, Debug)]
38pub enum TransactionEvent<'t> {
39 Removed(Hash),
40 Included(&'t Transaction),
41 Executed(&'t SpentTransaction),
42}
43
44impl EventSource for TransactionEvent<'_> {
45 const COMPONENT: &'static str = "transactions";
46
47 fn topic(&self) -> &'static str {
48 match self {
49 Self::Removed(_) => "removed",
50 Self::Executed(_) => "executed",
51 Self::Included(_) => "included",
52 }
53 }
54 fn data(&self) -> Option<serde_json::Value> {
55 match self {
56 Self::Removed(_) => None,
57 Self::Executed(t) => serde_json::to_value(t).ok(),
58 Self::Included(t) => serde_json::to_value(t).ok(),
59 }
60 }
61 fn entity(&self) -> String {
62 let hash = match self {
63 Self::Removed(hash) => *hash,
64 Self::Executed(tx) => tx.inner.id(),
65 Self::Included(tx) => tx.id(),
66 };
67 hex::encode(hash)
68 }
69}
70use base64::engine::general_purpose::STANDARD as BASE64_ENGINE;
71use base64::Engine;
72use dusk_bytes::Serializable;
73use dusk_core::transfer::Transaction as ProtocolTransaction;
74use serde::ser::{Serialize, SerializeStruct, Serializer};
75
76impl Serialize for Transaction {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: Serializer,
80 {
81 let mut state = serializer.serialize_struct("Transaction", 1)?;
82 match &self.inner {
83 ProtocolTransaction::Phoenix(p) => {
84 state.serialize_field("type", "phoenix")?;
85
86 let root = p.root().to_bytes();
87 state.serialize_field("root", &hex::encode(root))?;
88
89 let nullifiers: Vec<_> = p
90 .nullifiers()
91 .iter()
92 .map(|n| hex::encode(n.to_bytes()))
93 .collect();
94 state.serialize_field("nullifiers", &nullifiers)?;
95 }
96 ProtocolTransaction::Moonlight(m) => {
97 state.serialize_field("type", "moonlight")?;
98
99 let sender = m.sender();
100 let sender = bs58::encode(sender.to_bytes()).into_string();
101 state.serialize_field("sender", &sender)?;
102
103 let receiver = m.receiver().map(|receiver| {
104 bs58::encode(receiver.to_bytes()).into_string()
105 });
106 state.serialize_field("receiver", &receiver)?;
107
108 state.serialize_field("value", &m.value())?;
109
110 state.serialize_field("nonce", &m.nonce())?;
111 }
112 }
113
114 let tx = &self.inner;
115
116 state.serialize_field("deposit", &tx.deposit())?;
117
118 let notes: Vec<Note> = tx.outputs().iter().map(|n| n.into()).collect();
119
120 if !notes.is_empty() {
121 state.serialize_field("outputs", ¬es)?;
122 }
123
124 let fee = {
125 let mut fee = HashMap::new();
126 fee.insert("gas_limit", tx.gas_limit().to_string());
127 fee.insert("gas_price", tx.gas_price().to_string());
128
129 let encoded_address = match tx.refund_address() {
130 RefundAddress::Phoenix(address) => {
131 bs58::encode(address.to_bytes()).into_string()
132 }
133 RefundAddress::Moonlight(address) => {
134 bs58::encode(address.to_bytes()).into_string()
135 }
136 };
137 fee.insert("refund_address", encoded_address);
138 if let ProtocolTransaction::Phoenix(tx) = tx {
139 fee.insert(
140 "phoenix sender",
141 hex::encode(tx.sender().to_bytes()),
142 );
143 }
144
145 fee
146 };
147
148 state.serialize_field("fee", &fee)?;
149
150 let call = tx.call().map(|c| {
151 let mut call = HashMap::new();
152 call.insert("contract", hex::encode(c.contract));
153 call.insert("fn_name", c.fn_name.to_string());
154 call.insert("fn_args", BASE64_ENGINE.encode(&c.fn_args));
155 call
156 });
157 state.serialize_field("call", &call)?;
158
159 state.serialize_field("is_deploy", &tx.deploy().is_some())?;
160 state.serialize_field("memo", &tx.memo().map(hex::encode))?;
161 state.end()
162 }
163}
164
165struct Note<'a>(&'a dusk_core::transfer::phoenix::Note);
166
167impl<'a> From<&'a dusk_core::transfer::phoenix::Note> for Note<'a> {
168 fn from(value: &'a dusk_core::transfer::phoenix::Note) -> Self {
169 Self(value)
170 }
171}
172
173impl Serialize for Note<'_> {
174 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
175 where
176 S: Serializer,
177 {
178 let mut state = serializer.serialize_struct("Note", 5)?;
179 let n = self.0;
180
181 state.serialize_field("type", &(n.note_type() as u8))?;
182
183 let commitment = [
184 hex::encode(n.value_commitment().get_u().to_bytes()),
185 hex::encode(n.value_commitment().get_v().to_bytes()),
186 ];
187 state.serialize_field("value_commitment", &commitment)?;
188
189 let stealth_address = n.stealth_address().to_bytes();
190 state.serialize_field(
191 "stealth_address",
192 &bs58::encode(stealth_address).into_string(),
193 )?;
194
195 state.serialize_field("value_enc", &hex::encode(n.value_enc()))?;
196 state.serialize_field("sender", &hex::encode(n.sender().to_bytes()))?;
197 state.end()
198 }
199}