openmina_node_native/graphql/
snark.rs

1use juniper::{graphql_object, GraphQLObject};
2use ledger::scan_state::scan_state::{AvailableJobMessage, ParallelScanAvailableJob};
3use mina_p2p_messages::v2::{
4    MinaBaseFeeExcessStableV1, MinaStateBlockchainStateValueStableV2SignedAmount,
5    TransactionSnarkScanStateTransactionWithWitnessStableV2, TransactionSnarkStableV2,
6};
7use node::snark_pool::JobState;
8
9use super::{account::GraphQLAccount, Context, ConversionError, GraphQLPublicKey};
10
11#[derive(GraphQLObject, Debug)]
12#[graphql(description = "A Mina block")]
13pub struct GraphQLPendingSnarkWork {
14    /// Work bundle with one or two snark work
15    pub work_bundle: Vec<GraphQLWorkDescription>,
16}
17
18#[derive(GraphQLObject, Debug)]
19pub struct GraphQLWorkDescription {
20    /// Base58Check-encoded hash of the source first-pass ledger
21    pub source_first_pass_ledger_hash: String,
22    /// Base58Check-encoded hash of the target first-pass ledger
23    pub target_first_pass_ledger_hash: String,
24    /// Base58Check-encoded hash of the source second-pass ledger
25    pub source_second_pass_ledger_hash: String,
26    /// Base58Check-encoded hash of the target second-pass ledger
27    pub target_second_pass_ledger_hash: String,
28    /// Total transaction fee that is not accounted for in the transition from source ledger to target ledger
29    pub fee_excess: GraphQLFeeExcesses,
30    /// Increase/Decrease in total supply
31    pub supply_change: GraphQLSupplyChange,
32    /// Increase in total supply
33    pub supply_increase: String,
34    /// Unique identifier for a snark work
35    pub work_id: i32,
36}
37
38#[derive(GraphQLObject, Debug)]
39pub struct GraphQLFeeExcesses {
40    pub fee_token_left: String,
41    pub fee_excess_left: GraphQLFeeExcess,
42    pub fee_token_right: String,
43    pub fee_excess_right: GraphQLFeeExcess,
44}
45
46#[derive(GraphQLObject, Debug)]
47pub struct GraphQLFeeExcess {
48    pub fee_magnitude: String,
49    pub sign: String,
50}
51
52#[derive(GraphQLObject, Debug)]
53pub struct GraphQLSupplyChange {
54    pub amount_magnitude: String,
55    pub sign: String,
56}
57
58impl TryFrom<JobState> for GraphQLPendingSnarkWork {
59    type Error = ConversionError;
60
61    fn try_from(value: JobState) -> Result<Self, Self::Error> {
62        let mut work_bundle = Vec::new();
63
64        for job in value.job.into_iter() {
65            work_bundle.push(GraphQLWorkDescription::try_from(job)?);
66        }
67
68        Ok(Self { work_bundle })
69    }
70}
71
72impl TryFrom<AvailableJobMessage> for GraphQLWorkDescription {
73    type Error = ConversionError;
74
75    fn try_from(value: AvailableJobMessage) -> Result<Self, Self::Error> {
76        match value {
77            ParallelScanAvailableJob::Base(base) => GraphQLWorkDescription::try_from(base),
78            ParallelScanAvailableJob::Merge { left, .. } => {
79                GraphQLWorkDescription::try_from(left.0 .0)
80            }
81        }
82    }
83}
84
85impl TryFrom<MinaBaseFeeExcessStableV1> for GraphQLFeeExcesses {
86    type Error = ConversionError;
87
88    fn try_from(value: MinaBaseFeeExcessStableV1) -> Result<Self, Self::Error> {
89        Ok(Self {
90            fee_token_left: value.0.token.to_string(),
91            fee_excess_left: GraphQLFeeExcess {
92                fee_magnitude: value.0.amount.magnitude.to_string(),
93                sign: value.0.amount.sgn.to_string(),
94            },
95            fee_token_right: value.1.token.to_string(),
96            fee_excess_right: GraphQLFeeExcess {
97                fee_magnitude: value.1.amount.magnitude.to_string(),
98                sign: value.1.amount.sgn.to_string(),
99            },
100        })
101    }
102}
103
104impl TryFrom<MinaStateBlockchainStateValueStableV2SignedAmount> for GraphQLSupplyChange {
105    type Error = ConversionError;
106
107    fn try_from(
108        value: MinaStateBlockchainStateValueStableV2SignedAmount,
109    ) -> Result<Self, Self::Error> {
110        Ok(Self {
111            amount_magnitude: value.magnitude.to_string(),
112            sign: value.sgn.to_string(),
113        })
114    }
115}
116
117impl TryFrom<TransactionSnarkScanStateTransactionWithWitnessStableV2> for GraphQLWorkDescription {
118    type Error = ConversionError;
119
120    fn try_from(
121        value: TransactionSnarkScanStateTransactionWithWitnessStableV2,
122    ) -> Result<Self, Self::Error> {
123        Ok(Self {
124            source_first_pass_ledger_hash: value.statement.source.first_pass_ledger.to_string(),
125            target_first_pass_ledger_hash: value.statement.target.first_pass_ledger.to_string(),
126            source_second_pass_ledger_hash: value.statement.source.second_pass_ledger.to_string(),
127            target_second_pass_ledger_hash: value.statement.target.second_pass_ledger.to_string(),
128            fee_excess: GraphQLFeeExcesses::try_from(value.statement.fee_excess.clone())?,
129            supply_change: GraphQLSupplyChange::try_from(value.statement.supply_increase.clone())?,
130            supply_increase: value.statement.supply_increase.magnitude.to_string(),
131            work_id: 0,
132        })
133    }
134}
135
136impl TryFrom<TransactionSnarkStableV2> for GraphQLWorkDescription {
137    type Error = ConversionError;
138
139    fn try_from(value: TransactionSnarkStableV2) -> Result<Self, Self::Error> {
140        Ok(Self {
141            source_first_pass_ledger_hash: value.statement.source.first_pass_ledger.to_string(),
142            target_first_pass_ledger_hash: value.statement.target.first_pass_ledger.to_string(),
143            source_second_pass_ledger_hash: value.statement.source.second_pass_ledger.to_string(),
144            target_second_pass_ledger_hash: value.statement.target.second_pass_ledger.to_string(),
145            fee_excess: GraphQLFeeExcesses::try_from(value.statement.fee_excess.clone())?,
146            supply_change: GraphQLSupplyChange::try_from(value.statement.supply_increase.clone())?,
147            supply_increase: value.statement.supply_increase.magnitude.to_string(),
148            work_id: 0,
149        })
150    }
151}
152
153pub(crate) struct GraphQLSnarkWorker {
154    pub key: GraphQLPublicKey,
155    pub account: Option<GraphQLAccount>,
156    pub fee: String,
157}
158
159#[graphql_object(context = Context)]
160#[graphql(description = "A snark worker")]
161impl GraphQLSnarkWorker {
162    pub fn key(&self) -> String {
163        self.key.to_string()
164    }
165
166    pub fn fee(&self) -> String {
167        self.fee.to_string()
168    }
169
170    pub fn account(&self) -> Option<GraphQLAccount> {
171        self.account.clone()
172    }
173}