snark/user_command_verify/
snark_user_command_verify_reducer.rs

1use openmina_core::{bug_condition, Substate, SubstateAccess};
2use redux::EnablingCondition;
3
4use crate::user_command_verify_effectful::SnarkUserCommandVerifyEffectfulAction;
5
6use super::{
7    SnarkUserCommandVerifyAction, SnarkUserCommandVerifyActionWithMetaRef,
8    SnarkUserCommandVerifyState, SnarkUserCommandVerifyStatus,
9};
10
11pub fn reducer<State, Action>(
12    mut state: Substate<Action, State, SnarkUserCommandVerifyState>,
13    action: SnarkUserCommandVerifyActionWithMetaRef<'_>,
14) where
15    State: SubstateAccess<SnarkUserCommandVerifyState> + SubstateAccess<crate::SnarkState>,
16    Action: From<SnarkUserCommandVerifyAction>
17        + From<SnarkUserCommandVerifyEffectfulAction>
18        + From<redux::AnyAction>
19        + EnablingCondition<State>,
20{
21    let (action, meta) = action.split();
22    match action {
23        SnarkUserCommandVerifyAction::Init {
24            commands,
25            req_id,
26            from_source,
27            on_success,
28            on_error,
29        } => {
30            let substate = state.get_substate_mut().unwrap();
31
32            substate.jobs.add(SnarkUserCommandVerifyStatus::Init {
33                time: meta.time(),
34                commands: commands.clone(),
35                from_source: *from_source,
36                on_success: on_success.clone(),
37                on_error: on_error.clone(),
38            });
39
40            // Dispatch
41            let dispatcher = state.into_dispatcher();
42            dispatcher.push(SnarkUserCommandVerifyEffectfulAction::Init {
43                req_id: *req_id,
44                commands: commands.clone(),
45            });
46            dispatcher.push(SnarkUserCommandVerifyAction::Pending { req_id: *req_id });
47        }
48        SnarkUserCommandVerifyAction::Pending { req_id } => {
49            let substate = state.get_substate_mut().unwrap();
50
51            let Some(req) = substate.jobs.get_mut(*req_id) else {
52                bug_condition!("State for job not found in SnarkUserCommandVerifyAction::Pending");
53                return;
54            };
55            let SnarkUserCommandVerifyStatus::Init {
56                commands,
57                from_source,
58                on_success,
59                on_error,
60                ..
61            } = req
62            else {
63                bug_condition!("Unexpected state in SnarkUserCommandVerifyAction::Pending");
64                return;
65            };
66
67            *req = SnarkUserCommandVerifyStatus::Pending {
68                time: meta.time(),
69                commands: std::mem::take(commands),
70                from_source: std::mem::take(from_source),
71                on_success: on_success.clone(),
72                on_error: on_error.clone(),
73            };
74        }
75        SnarkUserCommandVerifyAction::Error { req_id, error } => {
76            let substate = state.get_substate_mut().unwrap();
77
78            let Some(req) = substate.jobs.get_mut(*req_id) else {
79                bug_condition!("State for job not found in SnarkUserCommandVerifyAction::Error");
80                return;
81            };
82            let SnarkUserCommandVerifyStatus::Pending { commands, .. } = req else {
83                bug_condition!("Unexpected state in SnarkUserCommandVerifyAction::Error");
84                return;
85            };
86
87            *req = SnarkUserCommandVerifyStatus::Error {
88                time: meta.time(),
89                commands: std::mem::take(commands),
90                error: error.clone(),
91            };
92
93            // Dispatch
94            let dispatcher = state.into_dispatcher();
95            // TODO: dispatch on error callback
96            dispatcher.push(SnarkUserCommandVerifyAction::Finish { req_id: *req_id });
97        }
98        SnarkUserCommandVerifyAction::Success { req_id, commands } => {
99            let substate = state.get_substate_mut().unwrap();
100            let Some(req) = substate.jobs.get_mut(*req_id) else {
101                bug_condition!("State for job not found in SnarkUserCommandVerifyAction::Success");
102                return;
103            };
104            let SnarkUserCommandVerifyStatus::Pending {
105                from_source,
106                on_success,
107                ..
108            } = req
109            else {
110                bug_condition!("Unexpected state in SnarkUserCommandVerifyAction::Success");
111                return;
112            };
113
114            let from_source = std::mem::take(from_source);
115            let commands: Vec<ledger::scan_state::transaction_logic::valid::UserCommand> =
116                commands.clone();
117            let on_success = on_success.clone();
118
119            *req = SnarkUserCommandVerifyStatus::Success {
120                time: meta.time(),
121                commands: commands.clone(), // std::mem::take(commands),
122            };
123
124            // Dispatch
125            let dispatcher = state.into_dispatcher();
126            dispatcher.push_callback(on_success, (*req_id, commands, from_source));
127            dispatcher.push(SnarkUserCommandVerifyAction::Finish { req_id: *req_id });
128        }
129        SnarkUserCommandVerifyAction::Finish { req_id } => {
130            let substate = state.get_substate_mut().unwrap();
131            substate.jobs.remove(*req_id);
132        }
133    }
134}