1use std::str::FromStr;
2
3use juniper::{GraphQLInputObject, GraphQLObject};
4use ledger::{FpExt, VerificationKey};
5use mina_p2p_messages::{
6 bigint::BigInt,
7 list::List,
8 pseq::PaddedSeq,
9 string::{TokenSymbol, ZkAppUri},
10 v2::{
11 CurrencyAmountStableV1, CurrencyBalanceStableV1, CurrencyFeeStableV1,
12 MinaBaseAccountUpdateAccountPreconditionStableV1,
13 MinaBaseAccountUpdateAuthorizationKindStableV1, MinaBaseAccountUpdateBodyEventsStableV1,
14 MinaBaseAccountUpdateBodyFeePayerStableV1, MinaBaseAccountUpdateBodyStableV1,
15 MinaBaseAccountUpdateFeePayerStableV1, MinaBaseAccountUpdateMayUseTokenStableV1,
16 MinaBaseAccountUpdatePreconditionsStableV1, MinaBaseAccountUpdateTStableV1,
17 MinaBaseAccountUpdateUpdateStableV1, MinaBaseAccountUpdateUpdateStableV1AppStateA,
18 MinaBaseAccountUpdateUpdateStableV1Delegate,
19 MinaBaseAccountUpdateUpdateStableV1Permissions, MinaBaseAccountUpdateUpdateStableV1Timing,
20 MinaBaseAccountUpdateUpdateStableV1TokenSymbol,
21 MinaBaseAccountUpdateUpdateStableV1VerificationKey,
22 MinaBaseAccountUpdateUpdateStableV1VotingFor, MinaBaseAccountUpdateUpdateStableV1ZkappUri,
23 MinaBaseAccountUpdateUpdateTimingInfoStableV1, MinaBaseControlStableV2,
24 MinaBasePermissionsStableV2, MinaBaseReceiptChainHashStableV1,
25 MinaBaseSignedCommandMemoStableV1, MinaBaseUserCommandStableV2,
26 MinaBaseVerificationKeyWireStableV1, MinaBaseZkappCommandTStableV1WireStableV1,
27 MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesA,
28 MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAA,
29 MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAACallsA,
30 MinaBaseZkappPreconditionAccountStableV2, MinaBaseZkappPreconditionAccountStableV2Balance,
31 MinaBaseZkappPreconditionAccountStableV2BalanceA,
32 MinaBaseZkappPreconditionAccountStableV2Delegate,
33 MinaBaseZkappPreconditionAccountStableV2ProvedState,
34 MinaBaseZkappPreconditionAccountStableV2ReceiptChainHash,
35 MinaBaseZkappPreconditionAccountStableV2StateA,
36 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1,
37 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochLedger,
38 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochSeed,
39 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint,
40 MinaBaseZkappPreconditionProtocolStateStableV1,
41 MinaBaseZkappPreconditionProtocolStateStableV1Amount,
42 MinaBaseZkappPreconditionProtocolStateStableV1AmountA,
43 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot,
44 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlotA,
45 MinaBaseZkappPreconditionProtocolStateStableV1Length,
46 MinaBaseZkappPreconditionProtocolStateStableV1LengthA,
47 MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash,
48 MinaNumbersGlobalSlotSinceGenesisMStableV1, MinaNumbersGlobalSlotSpanStableV1,
49 MinaStateBlockchainStateValueStableV2SignedAmount, PicklesProofProofsVerifiedMaxStableV2,
50 StateHash,
51 },
52};
53
54use node::account::AccountPublicKey;
55use serde::Deserialize;
56
57use super::{
58 account::{GraphQLTiming, InputGraphQLTiming},
59 ConversionError,
60};
61
62#[derive(GraphQLInputObject, Debug)]
63pub struct SendZkappInput {
64 pub zkapp_command: InputGraphQLZkappCommand,
65}
66
67impl TryFrom<SendZkappInput> for MinaBaseUserCommandStableV2 {
68 type Error = ConversionError;
69 fn try_from(value: SendZkappInput) -> Result<Self, Self::Error> {
70 value.zkapp_command.try_into()
71 }
72}
73
74#[derive(GraphQLObject, Debug)]
75pub struct GraphQLSendZkappResponse {
76 pub zkapp: GraphQLZkapp,
77}
78
79#[derive(GraphQLObject, Debug)]
80pub struct GraphQLZkapp {
81 pub hash: String,
82 pub failure_reason: Option<Vec<GraphQLFailureReason>>,
83 pub id: String,
85 pub zkapp_command: GraphQLZkappCommand,
86}
87
88#[derive(GraphQLInputObject, Debug)]
89pub struct InputGraphQLZkapp {
90 pub zkapp_command: InputGraphQLZkappCommand,
95}
96
97#[derive(GraphQLObject, Debug)]
98pub struct GraphQLZkappCommand {
99 pub memo: String,
100 pub account_updates: Vec<GraphQLAccountUpdate>,
101 pub fee_payer: GraphQLFeePayer,
102}
103
104#[derive(GraphQLInputObject, Debug)]
105pub struct InputGraphQLZkappCommand {
106 pub memo: Option<String>,
107 pub account_updates: Vec<InputGraphQLAccountUpdate>,
108 pub fee_payer: InputGraphQLFeePayer,
109}
110
111impl TryFrom<MinaBaseZkappCommandTStableV1WireStableV1> for GraphQLZkapp {
112 type Error = ConversionError;
113
114 fn try_from(zkapp: MinaBaseZkappCommandTStableV1WireStableV1) -> Result<Self, Self::Error> {
115 let account_updates = zkapp
116 .account_updates
117 .clone()
118 .into_iter()
119 .map(|v| v.elt.account_update.try_into())
120 .collect::<Result<Vec<_>, _>>()?;
121
122 Ok(GraphQLZkapp {
123 hash: zkapp.hash()?.to_string(),
124 failure_reason: None,
125 id: zkapp.to_base64()?,
126 zkapp_command: GraphQLZkappCommand {
127 memo: zkapp.memo.to_base58check(),
128 account_updates,
129 fee_payer: GraphQLFeePayer::from(zkapp.fee_payer),
130 },
131 })
132 }
133}
134
135impl TryFrom<MinaBaseUserCommandStableV2> for GraphQLSendZkappResponse {
136 type Error = ConversionError;
137 fn try_from(value: MinaBaseUserCommandStableV2) -> Result<Self, Self::Error> {
138 if let MinaBaseUserCommandStableV2::ZkappCommand(zkapp) = value {
139 Ok(GraphQLSendZkappResponse {
140 zkapp: GraphQLZkapp::try_from(zkapp)?,
141 })
142 } else {
143 Err(ConversionError::WrongVariant)
144 }
145 }
146}
147
148impl TryFrom<InputGraphQLZkappCommand> for MinaBaseUserCommandStableV2 {
149 type Error = ConversionError;
150 fn try_from(value: InputGraphQLZkappCommand) -> Result<Self, Self::Error> {
151 Ok(MinaBaseUserCommandStableV2::ZkappCommand(
152 MinaBaseZkappCommandTStableV1WireStableV1 {
153 fee_payer: value.fee_payer.try_into()?,
154 account_updates: try_tree_from_account_updates(List::from_iter(
155 value.account_updates,
156 ))?,
157 memo: if let Some(memo) = value.memo {
158 MinaBaseSignedCommandMemoStableV1::from_base58check(&memo)
159 } else {
160 let empty_memo = ledger::scan_state::transaction_logic::Memo::empty();
161 MinaBaseSignedCommandMemoStableV1::from(&empty_memo)
162 },
163 },
164 ))
165 }
166}
167
168fn try_tree_from_account_updates(
170 updates: List<InputGraphQLAccountUpdate>,
171) -> Result<List<MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesA>, ConversionError> {
172 let result =
173 try_tree_from_account_updates_aux(updates)?
174 .into_iter()
175 .map(|update| {
176 let MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAACallsA {
177 elt,
178 stack_hash,
179 } = update;
180 let MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAA {
181 account_update,
182 account_update_digest,
183 calls,
184 } = *elt;
185 let elt = MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAA {
186 account_update,
187 account_update_digest,
188 calls,
189 };
190 MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesA { elt, stack_hash }
191 })
192 .collect();
193 Ok(result)
194}
195
196fn try_tree_from_account_updates_aux(
197 updates: List<InputGraphQLAccountUpdate>,
198) -> Result<List<MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAACallsA>, ConversionError>
199{
200 let mut result = List::new();
201 let mut iter = updates.into_iter().peekable();
202
203 while let Some(account_update) = iter.next() {
204 let depth = account_update.body.call_depth;
205 let mut children = List::new();
206
207 while let Some(next_p) = iter.peek() {
208 if next_p.body.call_depth > depth {
209 children.push_back(iter.next().unwrap());
211 } else {
212 break;
213 }
214 }
215
216 let calls = try_tree_from_account_updates_aux(children)?;
217
218 result.push_back(
219 MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAACallsA {
220 elt: Box::new(MinaBaseZkappCommandTStableV1WireStableV1AccountUpdatesAA {
221 account_update: account_update.try_into()?, account_update_digest: (),
223 calls,
224 }),
225 stack_hash: (),
226 },
227 );
228 }
229
230 Ok(result)
231}
232
233#[derive(GraphQLObject, Debug)]
234pub struct GraphQLFeePayer {
235 pub body: GraphQLFeePayerBody,
236 pub authorization: String,
237}
238
239#[derive(GraphQLInputObject, Debug)]
240pub struct InputGraphQLFeePayer {
241 pub body: InputGraphQLFeePayerBody,
242 pub authorization: String,
243}
244
245#[derive(GraphQLObject, Debug)]
246pub struct GraphQLFeePayerBody {
247 pub public_key: String,
248 pub fee: String,
249 pub valid_until: Option<String>,
250 pub nonce: String,
251}
252
253#[derive(GraphQLInputObject, Debug)]
254pub struct InputGraphQLFeePayerBody {
255 pub public_key: String,
256 pub fee: String,
257 pub valid_until: Option<String>,
258 pub nonce: String,
259}
260
261#[derive(GraphQLObject, Debug)]
262pub struct GraphQLAccountUpdate {
263 pub body: GraphQLAccountUpdateBody,
264 pub authorization: GraphQLAuthorization,
265}
266
267#[derive(GraphQLInputObject, Debug)]
268pub struct InputGraphQLAccountUpdate {
269 pub body: InputGraphQLAccountUpdateBody,
270 pub authorization: InputGraphQLAuthorization,
271}
272
273#[derive(GraphQLObject, Debug)]
274pub struct GraphQLAuthorization {
275 pub proof: Option<String>,
276 pub signature: Option<String>,
277}
278
279#[derive(GraphQLInputObject, Debug)]
280pub struct InputGraphQLAuthorization {
281 pub proof: Option<String>,
282 pub signature: Option<String>,
283}
284
285impl TryFrom<MinaBaseControlStableV2> for GraphQLAuthorization {
286 type Error = ConversionError;
287
288 fn try_from(value: MinaBaseControlStableV2) -> Result<Self, Self::Error> {
289 let auth = match value {
290 MinaBaseControlStableV2::Signature(signature) => GraphQLAuthorization {
291 proof: None,
292 signature: Some(signature.to_string()),
293 },
294 MinaBaseControlStableV2::Proof(proof) => GraphQLAuthorization {
295 proof: Some(
296 serde_json::to_string_pretty(&proof)?
297 .trim_matches('"')
298 .to_string(),
299 ),
300 signature: None,
301 },
302 MinaBaseControlStableV2::NoneGiven => GraphQLAuthorization {
303 proof: None,
304 signature: None,
305 },
306 };
307 Ok(auth)
308 }
309}
310
311impl TryFrom<InputGraphQLAuthorization> for MinaBaseControlStableV2 {
312 type Error = ConversionError;
313
314 fn try_from(value: InputGraphQLAuthorization) -> Result<Self, Self::Error> {
315 match (value.signature, value.proof) {
316 (Some(signature), None) => {
317 Ok(MinaBaseControlStableV2::Signature(signature.parse()?))
319 }
320 (None, Some(proof)) => {
321 let proof = PicklesProofProofsVerifiedMaxStableV2::deserialize(
323 serde_json::Value::String(proof),
324 )?;
325 Ok(MinaBaseControlStableV2::Proof(Box::new(proof)))
326 }
327 (None, None) => Ok(MinaBaseControlStableV2::NoneGiven),
328 _ => Err(ConversionError::Custom(
329 "Either signature or proof must be provided, but not both".into(),
330 )),
331 }
332 }
333}
334
335#[derive(GraphQLObject, Debug)]
336pub struct GraphQLAccountUpdateBody {
337 pub public_key: String,
338 pub token_id: String,
339 pub use_full_commitment: bool,
340 pub increment_nonce: bool,
341 pub update: GraphQLAccountUpdateUpdate,
342 pub balance_change: GraphQLBalanceChange,
343 pub events: Vec<Vec<String>>,
344 pub actions: Vec<Vec<String>>,
345 pub call_data: String,
346 pub call_depth: i32,
347 pub preconditions: GraphQLPreconditions,
348 pub may_use_token: GraphQLMayUseToken,
349 pub authorization_kind: GraphQLAuthorizationKind,
350 pub implicit_account_creation_fee: bool,
351}
352
353#[derive(GraphQLInputObject, Debug)]
354pub struct InputGraphQLAccountUpdateBody {
355 pub public_key: String,
356 pub token_id: String,
357 pub use_full_commitment: bool,
358 pub increment_nonce: bool,
359 pub update: InputGraphQLAccountUpdateUpdate,
360 pub balance_change: InputGraphQLBalanceChange,
361 pub events: Vec<Vec<String>>,
362 pub actions: Vec<Vec<String>>,
363 pub call_data: String,
364 pub call_depth: i32,
365 pub preconditions: InputGraphQLPreconditions,
366 pub may_use_token: InputGraphQLMayUseToken,
367 pub authorization_kind: InputGraphQLAuthorizationKind,
368 pub implicit_account_creation_fee: bool,
369}
370
371#[derive(GraphQLObject, Debug)]
372pub struct GraphQLAuthorizationKind {
373 pub is_signed: bool,
374 pub is_proved: bool,
375 pub verification_key_hash: Option<String>,
376}
377
378#[derive(GraphQLInputObject, Debug)]
379pub struct InputGraphQLAuthorizationKind {
380 pub is_signed: bool,
381 pub is_proved: bool,
382 pub verification_key_hash: Option<String>,
383}
384
385impl From<MinaBaseAccountUpdateAuthorizationKindStableV1> for GraphQLAuthorizationKind {
386 fn from(value: MinaBaseAccountUpdateAuthorizationKindStableV1) -> Self {
387 match value {
388 MinaBaseAccountUpdateAuthorizationKindStableV1::Signature => GraphQLAuthorizationKind {
389 is_signed: true,
390 is_proved: false,
391 verification_key_hash: None,
392 },
393 MinaBaseAccountUpdateAuthorizationKindStableV1::Proof(proof) => {
394 GraphQLAuthorizationKind {
395 is_signed: false,
396 is_proved: true,
397 verification_key_hash: Some(proof.to_decimal()),
398 }
399 }
400 MinaBaseAccountUpdateAuthorizationKindStableV1::NoneGiven => GraphQLAuthorizationKind {
401 is_signed: false,
402 is_proved: false,
403 verification_key_hash: None,
404 },
405 }
406 }
407}
408
409impl TryFrom<InputGraphQLAuthorizationKind> for MinaBaseAccountUpdateAuthorizationKindStableV1 {
410 type Error = ConversionError;
411 fn try_from(value: InputGraphQLAuthorizationKind) -> Result<Self, Self::Error> {
412 if value.is_signed {
413 return Ok(MinaBaseAccountUpdateAuthorizationKindStableV1::Signature);
414 }
415
416 if value.is_proved {
417 match &value.verification_key_hash {
418 Some(vk_hash) => {
419 let big_int = BigInt::from_decimal(vk_hash)?;
420 return Ok(MinaBaseAccountUpdateAuthorizationKindStableV1::Proof(
421 big_int,
422 ));
423 }
424 None => {
425 return Err(ConversionError::MissingField(
426 "verification_key_hash".to_string(),
427 ));
428 }
429 }
430 }
431
432 Ok(MinaBaseAccountUpdateAuthorizationKindStableV1::NoneGiven)
433 }
434}
435
436#[derive(GraphQLObject, Debug)]
437pub struct GraphQLMayUseToken {
438 pub parents_own_token: bool,
439 pub inherit_from_parent: bool,
440}
441
442#[derive(GraphQLInputObject, Debug)]
443pub struct InputGraphQLMayUseToken {
444 pub parents_own_token: bool,
445 pub inherit_from_parent: bool,
446}
447
448impl From<MinaBaseAccountUpdateMayUseTokenStableV1> for GraphQLMayUseToken {
449 fn from(value: MinaBaseAccountUpdateMayUseTokenStableV1) -> Self {
450 match value {
451 MinaBaseAccountUpdateMayUseTokenStableV1::ParentsOwnToken => GraphQLMayUseToken {
452 parents_own_token: true,
453 inherit_from_parent: false,
454 },
455 MinaBaseAccountUpdateMayUseTokenStableV1::InheritFromParent => GraphQLMayUseToken {
456 parents_own_token: false,
457 inherit_from_parent: true,
458 },
459 MinaBaseAccountUpdateMayUseTokenStableV1::No => GraphQLMayUseToken {
460 parents_own_token: false,
461 inherit_from_parent: false,
462 },
463 }
464 }
465}
466
467impl From<InputGraphQLMayUseToken> for MinaBaseAccountUpdateMayUseTokenStableV1 {
468 fn from(value: InputGraphQLMayUseToken) -> Self {
469 if value.parents_own_token {
470 MinaBaseAccountUpdateMayUseTokenStableV1::ParentsOwnToken
471 } else if value.inherit_from_parent {
472 MinaBaseAccountUpdateMayUseTokenStableV1::InheritFromParent
473 } else {
474 MinaBaseAccountUpdateMayUseTokenStableV1::No
475 }
476 }
477}
478
479#[derive(GraphQLObject, Debug)]
480pub struct GraphQLEvent {
481 pub event: String,
482 pub data: String,
483}
484
485#[derive(GraphQLInputObject, Debug)]
486pub struct InputGraphQLEvent {
487 pub event: String,
488 pub data: String,
489}
490
491#[derive(GraphQLObject, Debug)]
492pub struct GraphQLAction {
493 pub action: String,
494 pub data: String,
495}
496
497#[derive(GraphQLInputObject, Debug)]
498pub struct InputGraphQLAction {
499 pub action: String,
500 pub data: String,
501}
502
503#[derive(GraphQLObject, Debug)]
504pub struct GraphQLPreconditions {
505 pub network: GraphQLPreconditionsNetwork,
506 pub account: GraphQLPreconditionsAccount,
507 pub valid_while: Option<GraphQLPreconditionsNetworkBounds>,
508}
509
510#[derive(GraphQLInputObject, Debug)]
511pub struct InputGraphQLPreconditions {
512 pub network: InputGraphQLPreconditionsNetwork,
513 pub account: InputGraphQLPreconditionsAccount,
514 pub valid_while: Option<InputGraphQLPreconditionsNetworkBounds>,
515}
516
517#[derive(GraphQLObject, Debug)]
518pub struct GraphQLPreconditionsAccount {
519 pub balance: Option<GraphQLPreconditionsNetworkBounds>,
520 pub nonce: Option<GraphQLPreconditionsNetworkBounds>,
521 pub receipt_chain_hash: Option<String>,
522 pub delegate: Option<String>,
523 pub state: Vec<Option<String>>,
524 pub action_state: Option<String>,
525 pub proved_state: Option<bool>,
526 pub is_new: Option<bool>,
527}
528
529#[derive(GraphQLInputObject, Debug)]
530pub struct InputGraphQLPreconditionsAccount {
531 pub balance: Option<InputGraphQLPreconditionsNetworkBounds>,
532 pub nonce: Option<InputGraphQLPreconditionsNetworkBounds>,
533 pub receipt_chain_hash: Option<String>,
534 pub delegate: Option<String>,
535 pub state: Vec<Option<String>>,
536 pub action_state: Option<String>,
537 pub proved_state: Option<bool>,
538 pub is_new: Option<bool>,
539}
540
541impl From<MinaBaseAccountUpdateAccountPreconditionStableV1> for GraphQLPreconditionsAccount {
542 fn from(value: MinaBaseAccountUpdateAccountPreconditionStableV1) -> Self {
543 Self {
544 balance: if let MinaBaseZkappPreconditionAccountStableV2Balance::Check(v) =
545 value.0.balance
546 {
547 Some(GraphQLPreconditionsNetworkBounds {
548 upper: v.upper.as_u64().to_string(),
549 lower: v.lower.as_u64().to_string(),
550 })
551 } else {
552 None
553 },
554 nonce: if let MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(v) =
555 value.0.nonce
556 {
557 Some(GraphQLPreconditionsNetworkBounds {
558 upper: v.upper.as_u32().to_string(),
559 lower: v.lower.as_u32().to_string(),
560 })
561 } else {
562 None
563 },
564 receipt_chain_hash:
565 if let MinaBaseZkappPreconditionAccountStableV2ReceiptChainHash::Check(v) =
566 value.0.receipt_chain_hash
567 {
568 Some(v.to_decimal())
569 } else {
570 None
571 },
572 delegate: if let MinaBaseZkappPreconditionAccountStableV2Delegate::Check(v) =
573 value.0.delegate
574 {
575 Some(v.to_string())
576 } else {
577 None
578 },
579 state: value
580 .0
581 .state
582 .clone()
583 .iter()
584 .map(|v| {
585 if let MinaBaseZkappPreconditionAccountStableV2StateA::Check(state_value) = v {
586 Some(state_value.to_decimal())
587 } else {
588 None
589 }
590 })
591 .collect(),
592 action_state: if let MinaBaseZkappPreconditionAccountStableV2StateA::Check(value) =
593 value.0.action_state
594 {
595 Some(value.to_decimal())
596 } else {
597 None
598 },
599 proved_state: if let MinaBaseZkappPreconditionAccountStableV2ProvedState::Check(v) =
600 value.0.proved_state
601 {
602 Some(v)
603 } else {
604 None
605 },
606 is_new: if let MinaBaseZkappPreconditionAccountStableV2ProvedState::Check(v) =
607 value.0.is_new
608 {
609 Some(v)
610 } else {
611 None
612 },
613 }
614 }
615}
616
617impl TryFrom<InputGraphQLPreconditionsAccount>
618 for MinaBaseAccountUpdateAccountPreconditionStableV1
619{
620 type Error = ConversionError;
621 fn try_from(value: InputGraphQLPreconditionsAccount) -> Result<Self, Self::Error> {
622 let state: Result<Vec<_>, _> = value
623 .state
624 .iter()
625 .map(|v| {
626 if let Some(state) = v {
627 BigInt::from_decimal(state)
628 .map(MinaBaseZkappPreconditionAccountStableV2StateA::Check)
629 } else {
630 Ok(MinaBaseZkappPreconditionAccountStableV2StateA::Ignore)
631 }
632 })
633 .collect();
634
635 let state = state?;
636 Ok(Self(MinaBaseZkappPreconditionAccountStableV2 {
637 balance: if let Some(balance) = value.balance {
638 MinaBaseZkappPreconditionAccountStableV2Balance::Check(
639 MinaBaseZkappPreconditionAccountStableV2BalanceA {
640 lower: CurrencyBalanceStableV1(CurrencyAmountStableV1(
641 balance.lower.parse::<u64>()?.into(),
642 )),
643 upper: CurrencyBalanceStableV1(CurrencyAmountStableV1(
644 balance.upper.parse::<u64>()?.into(),
645 )),
646 },
647 )
648 } else {
649 MinaBaseZkappPreconditionAccountStableV2Balance::Ignore
650 },
651 nonce: if let Some(nonce) = value.nonce {
652 MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
653 MinaBaseZkappPreconditionProtocolStateStableV1LengthA {
654 lower: (nonce.lower.parse::<u32>()?).into(),
655 upper: (nonce.upper.parse::<u32>()?).into(),
656 },
657 )
658 } else {
659 MinaBaseZkappPreconditionProtocolStateStableV1Length::Ignore
660 },
661 receipt_chain_hash: if let Some(receipt_chain_hash) = value.receipt_chain_hash {
662 MinaBaseZkappPreconditionAccountStableV2ReceiptChainHash::Check(
663 MinaBaseReceiptChainHashStableV1(BigInt::from_decimal(&receipt_chain_hash)?),
664 )
665 } else {
666 MinaBaseZkappPreconditionAccountStableV2ReceiptChainHash::Ignore
667 },
668 delegate: if let Some(delegate) = value.delegate {
669 MinaBaseZkappPreconditionAccountStableV2Delegate::Check(
670 AccountPublicKey::from_str(&delegate)?.into(),
671 )
672 } else {
673 MinaBaseZkappPreconditionAccountStableV2Delegate::Ignore
674 },
675 state: PaddedSeq(
676 state
677 .try_into()
678 .map_err(|_| ConversionError::InvalidLength)?,
679 ),
680 action_state: if let Some(action_state) = value.action_state {
681 MinaBaseZkappPreconditionAccountStableV2StateA::Check(BigInt::from_decimal(
682 &action_state,
683 )?)
684 } else {
685 MinaBaseZkappPreconditionAccountStableV2StateA::Ignore
686 },
687 proved_state: if let Some(proved_state) = value.proved_state {
688 MinaBaseZkappPreconditionAccountStableV2ProvedState::Check(proved_state)
689 } else {
690 MinaBaseZkappPreconditionAccountStableV2ProvedState::Ignore
691 },
692 is_new: if let Some(is_new) = value.is_new {
693 MinaBaseZkappPreconditionAccountStableV2ProvedState::Check(is_new)
694 } else {
695 MinaBaseZkappPreconditionAccountStableV2ProvedState::Ignore
696 },
697 }))
698 }
699}
700#[derive(GraphQLObject, Debug)]
701pub struct GraphQLPreconditionsNetwork {
702 pub snarked_ledger_hash: Option<String>,
703 pub blockchain_length: Option<GraphQLPreconditionsNetworkBounds>,
704 pub min_window_density: Option<GraphQLPreconditionsNetworkBounds>,
705 pub total_currency: Option<GraphQLPreconditionsNetworkBounds>,
706 pub global_slot_since_genesis: Option<GraphQLPreconditionsNetworkBounds>,
707 pub staking_epoch_data: GraphQLPreconditionsNetworkEpochData,
708 pub next_epoch_data: GraphQLPreconditionsNetworkEpochData,
709}
710
711#[derive(GraphQLInputObject, Debug)]
712pub struct InputGraphQLPreconditionsNetwork {
713 pub snarked_ledger_hash: Option<String>,
714 pub blockchain_length: Option<InputGraphQLPreconditionsNetworkBounds>,
715 pub min_window_density: Option<InputGraphQLPreconditionsNetworkBounds>,
716 pub total_currency: Option<InputGraphQLPreconditionsNetworkBounds>,
717 pub global_slot_since_genesis: Option<InputGraphQLPreconditionsNetworkBounds>,
718 pub staking_epoch_data: InputGraphQLPreconditionsNetworkEpochData,
719 pub next_epoch_data: InputGraphQLPreconditionsNetworkEpochData,
720}
721
722#[derive(GraphQLObject, Debug)]
723pub struct GraphQLPreconditionsNetworkEpochData {
724 pub ledger: GraphQLPreconditionsNetworkLedger,
725 pub seed: Option<String>,
726 pub start_checkpoint: Option<String>,
727 pub lock_checkpoint: Option<String>,
728 pub epoch_length: Option<GraphQLPreconditionsNetworkBounds>,
729}
730
731#[derive(GraphQLInputObject, Debug)]
732pub struct InputGraphQLPreconditionsNetworkEpochData {
733 pub ledger: InputGraphQLPreconditionsNetworkLedger,
734 pub seed: Option<String>,
735 pub start_checkpoint: Option<String>,
736 pub lock_checkpoint: Option<String>,
737 pub epoch_length: Option<InputGraphQLPreconditionsNetworkBounds>,
738}
739
740#[derive(GraphQLObject, Debug)]
741pub struct GraphQLPreconditionsNetworkLedger {
742 pub hash: Option<String>,
743 pub total_currency: Option<GraphQLPreconditionsNetworkBounds>,
744}
745
746#[derive(GraphQLInputObject, Debug)]
747pub struct InputGraphQLPreconditionsNetworkLedger {
748 pub hash: Option<String>,
749 pub total_currency: Option<InputGraphQLPreconditionsNetworkBounds>,
750}
751#[derive(GraphQLObject, Debug)]
752pub struct GraphQLPreconditionsNetworkBounds {
753 pub upper: String,
754 pub lower: String,
755}
756
757#[derive(GraphQLInputObject, Debug)]
758pub struct InputGraphQLPreconditionsNetworkBounds {
759 pub upper: String,
760 pub lower: String,
761}
762
763impl From<MinaBaseZkappPreconditionProtocolStateEpochDataStableV1>
764 for GraphQLPreconditionsNetworkEpochData
765{
766 fn from(value: MinaBaseZkappPreconditionProtocolStateEpochDataStableV1) -> Self {
767 Self {
768 ledger: GraphQLPreconditionsNetworkLedger::from(value.ledger),
769 seed: if let MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochSeed::Check(v) = value.seed {
770 Some(v.to_string())
771 } else {
772 None
773 },
774 start_checkpoint: if let MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Check(v) = value.start_checkpoint {
775 Some(v.to_string())
776 } else {
777 None
778 },
779 lock_checkpoint: if let MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Check(v) = value.lock_checkpoint {
780 Some(v.to_string())
781 } else {
782 None
783 },
784 epoch_length: if let MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(v) = value.epoch_length {
785 Some(GraphQLPreconditionsNetworkBounds {
786 upper: v.upper.as_u32().to_string(),
787 lower: v.lower.as_u32().to_string(),
788 })
789 } else {
790 None
791 },
792 }
793 }
794}
795
796impl TryFrom<InputGraphQLPreconditionsNetworkEpochData>
797 for MinaBaseZkappPreconditionProtocolStateEpochDataStableV1
798{
799 type Error = ConversionError;
800 fn try_from(value: InputGraphQLPreconditionsNetworkEpochData) -> Result<Self, Self::Error> {
801 Ok(Self {
802 ledger: value.ledger.try_into()?,
803 seed: if let Some(seed) = value.seed {
804 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochSeed::Check(
805 seed.parse()?,
806 )
807 } else {
808 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochSeed::Ignore
809 },
810 start_checkpoint: if let Some(start_checkpoint) = value.start_checkpoint {
811 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Check(
812 start_checkpoint.parse()?,
813 )
814 } else {
815 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Ignore
816 },
817 lock_checkpoint: if let Some(lock_checkpoint) = value.lock_checkpoint {
818 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Check(
819 lock_checkpoint.parse()?,
820 )
821 } else {
822 MinaBaseZkappPreconditionProtocolStateEpochDataStableV1StartCheckpoint::Ignore
823 },
824 epoch_length: if let Some(epoch_length) = value.epoch_length {
825 MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
826 MinaBaseZkappPreconditionProtocolStateStableV1LengthA {
827 lower: (epoch_length.lower.parse::<u32>()?).into(),
828 upper: (epoch_length.upper.parse::<u32>()?).into(),
829 },
830 )
831 } else {
832 MinaBaseZkappPreconditionProtocolStateStableV1Length::Ignore
833 },
834 })
835 }
836}
837impl From<MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochLedger>
838 for GraphQLPreconditionsNetworkLedger
839{
840 fn from(value: MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochLedger) -> Self {
841 Self {
842 hash: if let MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Check(v) =
843 value.hash
844 {
845 Some(v.to_string())
846 } else {
847 None
848 },
849 total_currency: if let MinaBaseZkappPreconditionProtocolStateStableV1Amount::Check(v) =
850 value.total_currency
851 {
852 Some(GraphQLPreconditionsNetworkBounds {
853 upper: v.upper.as_u64().to_string(),
854 lower: v.lower.as_u64().to_string(),
855 })
856 } else {
857 None
858 },
859 }
860 }
861}
862
863impl TryFrom<InputGraphQLPreconditionsNetworkLedger>
864 for MinaBaseZkappPreconditionProtocolStateEpochDataStableV1EpochLedger
865{
866 type Error = ConversionError;
867 fn try_from(value: InputGraphQLPreconditionsNetworkLedger) -> Result<Self, Self::Error> {
868 Ok(Self {
869 hash: if let Some(hash) = value.hash {
870 MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Check(
871 hash.parse()?,
872 )
873 } else {
874 MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Ignore
875 },
876 total_currency: if let Some(total_currency) = value.total_currency {
877 MinaBaseZkappPreconditionProtocolStateStableV1Amount::Check(
878 MinaBaseZkappPreconditionProtocolStateStableV1AmountA {
879 lower: CurrencyAmountStableV1(
880 (total_currency.lower.parse::<u64>()?).into(),
881 ),
882 upper: CurrencyAmountStableV1(
883 (total_currency.upper.parse::<u64>()?).into(),
884 ),
885 },
886 )
887 } else {
888 MinaBaseZkappPreconditionProtocolStateStableV1Amount::Ignore
889 },
890 })
891 }
892}
893
894impl From<MinaBaseZkappPreconditionProtocolStateStableV1> for GraphQLPreconditionsNetwork {
895 fn from(value: MinaBaseZkappPreconditionProtocolStateStableV1) -> Self {
896 Self {
897 snarked_ledger_hash:
898 if let MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Check(v) =
899 value.snarked_ledger_hash
900 {
901 Some(v.to_string())
902 } else {
903 None
904 },
905 blockchain_length: if let MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
906 v,
907 ) = value.blockchain_length
908 {
909 Some(GraphQLPreconditionsNetworkBounds {
910 upper: v.upper.as_u32().to_string(),
911 lower: v.lower.as_u32().to_string(),
912 })
913 } else {
914 None
915 },
916 min_window_density: if let MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
917 v,
918 ) = value.min_window_density
919 {
920 Some(GraphQLPreconditionsNetworkBounds {
921 upper: v.upper.as_u32().to_string(),
922 lower: v.lower.as_u32().to_string(),
923 })
924 } else {
925 None
926 },
927 total_currency: if let MinaBaseZkappPreconditionProtocolStateStableV1Amount::Check(v) =
928 value.total_currency
929 {
930 Some(GraphQLPreconditionsNetworkBounds {
931 upper: v.upper.as_u64().to_string(),
932 lower: v.lower.as_u64().to_string(),
933 })
934 } else {
935 None
936 },
937 global_slot_since_genesis:
938 if let MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Check(v) =
939 value.global_slot_since_genesis
940 {
941 Some(GraphQLPreconditionsNetworkBounds {
942 upper: v.upper.as_u32().to_string(),
943 lower: v.lower.as_u32().to_string(),
944 })
945 } else {
946 None
947 },
948 staking_epoch_data: GraphQLPreconditionsNetworkEpochData::from(
949 value.staking_epoch_data,
950 ),
951 next_epoch_data: GraphQLPreconditionsNetworkEpochData::from(value.next_epoch_data),
952 }
953 }
954}
955
956impl TryFrom<InputGraphQLPreconditionsNetwork> for MinaBaseZkappPreconditionProtocolStateStableV1 {
957 type Error = ConversionError;
958 fn try_from(value: InputGraphQLPreconditionsNetwork) -> Result<Self, Self::Error> {
959 Ok(Self {
960 snarked_ledger_hash: if let Some(snarked_ledger_hash) = value.snarked_ledger_hash {
961 MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Check(
962 snarked_ledger_hash.parse()?,
963 )
964 } else {
965 MinaBaseZkappPreconditionProtocolStateStableV1SnarkedLedgerHash::Ignore
966 },
967 blockchain_length: if let Some(blockchain_length) = value.blockchain_length {
968 MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
969 MinaBaseZkappPreconditionProtocolStateStableV1LengthA {
970 lower: (blockchain_length.lower.parse::<u32>()?).into(),
971 upper: (blockchain_length.upper.parse::<u32>()?).into(),
972 },
973 )
974 } else {
975 MinaBaseZkappPreconditionProtocolStateStableV1Length::Ignore
976 },
977 min_window_density: if let Some(min_window_density) = value.min_window_density {
978 MinaBaseZkappPreconditionProtocolStateStableV1Length::Check(
979 MinaBaseZkappPreconditionProtocolStateStableV1LengthA {
980 lower: (min_window_density.lower.parse::<u32>()?).into(),
981 upper: (min_window_density.upper.parse::<u32>()?).into(),
982 },
983 )
984 } else {
985 MinaBaseZkappPreconditionProtocolStateStableV1Length::Ignore
986 },
987 total_currency: if let Some(total_currency) = value.total_currency {
988 MinaBaseZkappPreconditionProtocolStateStableV1Amount::Check(
989 MinaBaseZkappPreconditionProtocolStateStableV1AmountA {
990 lower: CurrencyAmountStableV1(
991 (total_currency.lower.parse::<u64>()?).into(),
992 ),
993 upper: CurrencyAmountStableV1(
994 (total_currency.upper.parse::<u64>()?).into(),
995 ),
996 },
997 )
998 } else {
999 MinaBaseZkappPreconditionProtocolStateStableV1Amount::Ignore
1000 },
1001 global_slot_since_genesis: if let Some(global_slot_since_genesis) =
1002 value.global_slot_since_genesis
1003 {
1004 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Check(
1005 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlotA {
1006 lower: MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1007 (global_slot_since_genesis.lower.parse::<u32>()?).into(),
1008 ),
1009 upper: MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1010 (global_slot_since_genesis.upper.parse::<u32>()?).into(),
1011 ),
1012 },
1013 )
1014 } else {
1015 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Ignore
1016 },
1017 staking_epoch_data: value.staking_epoch_data.try_into()?,
1018 next_epoch_data: value.next_epoch_data.try_into()?,
1019 })
1020 }
1021}
1022
1023#[derive(GraphQLObject, Debug)]
1024pub struct GraphQLAccountUpdateUpdate {
1025 pub app_state: Vec<Option<String>>,
1026 pub delegate: Option<String>,
1027 pub verification_key: Option<GraphQLVerificationKey>,
1028 pub permissions: Option<GraphQLAccountUpdateUpdatePermissions>,
1029 pub zkapp_uri: Option<String>,
1030 pub token_symbol: Option<String>,
1031 pub timing: Option<GraphQLTiming>,
1032 pub voting_for: Option<String>,
1033}
1034
1035#[derive(GraphQLObject, Debug)]
1036pub struct GraphQLVerificationKey {
1037 pub data: String,
1038 pub hash: String,
1039}
1040
1041#[derive(GraphQLInputObject, Debug)]
1042pub struct InputGraphQLAccountUpdateUpdate {
1043 pub app_state: Vec<Option<String>>,
1044 pub delegate: Option<String>,
1045 pub verification_key: Option<InputGraphQLVerificationKey>,
1046 pub permissions: Option<InputGraphQLAccountUpdateUpdatePermissions>,
1047 pub zkapp_uri: Option<String>,
1048 pub token_symbol: Option<String>,
1049 pub timing: Option<InputGraphQLTiming>,
1050 pub voting_for: Option<String>,
1051}
1052
1053#[derive(GraphQLInputObject, Debug)]
1054pub struct InputGraphQLVerificationKey {
1055 pub data: String,
1056 pub hash: String,
1057}
1058
1059#[derive(GraphQLObject, Debug)]
1060pub struct GraphQLAccountUpdateUpdatePermissions {
1061 pub edit_state: String,
1062 pub access: String,
1063 pub send: String,
1064 pub receive: String,
1065 pub set_delegate: String,
1066 pub set_permissions: String,
1067 pub set_verification_key: GraphQLSetVerificationKeyPermissions,
1068 pub set_zkapp_uri: String,
1069 pub edit_action_state: String,
1070 pub set_token_symbol: String,
1071 pub set_timing: String,
1072 pub set_voting_for: String,
1073 pub increment_nonce: String,
1074}
1075
1076#[derive(GraphQLObject, Debug)]
1077pub struct GraphQLSetVerificationKeyPermissions {
1078 pub auth: String,
1079 pub txn_version: String,
1080}
1081
1082#[derive(GraphQLInputObject, Debug)]
1083pub struct InputGraphQLAccountUpdateUpdatePermissions {
1084 pub edit_state: String,
1085 pub access: String,
1086 pub send: String,
1087 pub receive: String,
1088 pub set_delegate: String,
1089 pub set_permissions: String,
1090 pub set_verification_key: InputGraphQLSetVerificationKeyPermissions,
1091 pub set_zkapp_uri: String,
1092 pub edit_action_state: String,
1093 pub set_token_symbol: String,
1094 pub set_timing: String,
1095 pub set_voting_for: String,
1096 pub increment_nonce: String,
1097}
1098
1099#[derive(GraphQLInputObject, Debug)]
1100pub struct InputGraphQLSetVerificationKeyPermissions {
1101 pub auth: String,
1102 pub txn_version: String,
1103}
1104
1105impl From<MinaBasePermissionsStableV2> for GraphQLAccountUpdateUpdatePermissions {
1106 fn from(value: MinaBasePermissionsStableV2) -> Self {
1107 Self {
1108 edit_state: value.edit_state.to_string(),
1109 access: value.access.to_string(),
1110 send: value.send.to_string(),
1111 receive: value.receive.to_string(),
1112 set_delegate: value.set_delegate.to_string(),
1113 set_permissions: value.set_permissions.to_string(),
1114 set_verification_key: GraphQLSetVerificationKeyPermissions {
1115 auth: value.set_verification_key.0.to_string(),
1116 txn_version: value.set_verification_key.1.as_u32().to_string(),
1117 },
1118 set_zkapp_uri: value.set_zkapp_uri.to_string(),
1119 edit_action_state: value.edit_action_state.to_string(),
1120 set_token_symbol: value.set_token_symbol.to_string(),
1121 set_timing: value.set_timing.to_string(),
1122 set_voting_for: value.set_voting_for.to_string(),
1123 increment_nonce: value.increment_nonce.to_string(),
1124 }
1125 }
1126}
1127
1128impl TryFrom<InputGraphQLAccountUpdateUpdatePermissions> for MinaBasePermissionsStableV2 {
1129 type Error = ConversionError;
1130 fn try_from(value: InputGraphQLAccountUpdateUpdatePermissions) -> Result<Self, Self::Error> {
1131 Ok(Self {
1132 edit_state: value.edit_state.parse()?,
1133 access: value.access.parse()?,
1134 send: value.send.parse()?,
1135 receive: value.receive.parse()?,
1136 set_delegate: value.set_delegate.parse()?,
1137 set_permissions: value.set_permissions.parse()?,
1138 set_verification_key: (
1139 value.set_verification_key.auth.parse()?,
1140 value
1141 .set_verification_key
1142 .txn_version
1143 .parse::<u32>()?
1144 .into(),
1145 ),
1146 set_zkapp_uri: value.set_zkapp_uri.parse()?,
1147 edit_action_state: value.edit_action_state.parse()?,
1148 set_token_symbol: value.set_token_symbol.parse()?,
1149 set_timing: value.set_timing.parse()?,
1150 set_voting_for: value.set_voting_for.parse()?,
1151 increment_nonce: value.increment_nonce.parse()?,
1152 })
1153 }
1154}
1155
1156#[derive(GraphQLObject, Debug)]
1157pub struct GraphQLBalanceChange {
1158 pub magnitude: String,
1159 pub sgn: String,
1160}
1161
1162#[derive(GraphQLInputObject, Debug)]
1163pub struct InputGraphQLBalanceChange {
1164 pub magnitude: String,
1165 pub sgn: String,
1166}
1167
1168#[derive(GraphQLObject, Debug)]
1169pub struct GraphQLFailureReason {
1170 pub index: String,
1171 pub failures: Vec<String>,
1172}
1173
1174impl From<MinaStateBlockchainStateValueStableV2SignedAmount> for GraphQLBalanceChange {
1175 fn from(value: MinaStateBlockchainStateValueStableV2SignedAmount) -> Self {
1176 Self {
1177 magnitude: value.magnitude.as_u64().to_string(),
1178 sgn: value.sgn.to_string(),
1179 }
1180 }
1181}
1182
1183impl TryFrom<InputGraphQLBalanceChange> for MinaStateBlockchainStateValueStableV2SignedAmount {
1184 type Error = ConversionError;
1185 fn try_from(value: InputGraphQLBalanceChange) -> Result<Self, Self::Error> {
1186 Ok(Self {
1187 magnitude: CurrencyAmountStableV1(value.magnitude.parse::<u64>()?.into()),
1188 sgn: value
1189 .sgn
1190 .parse()
1191 .map_err(|_| ConversionError::WrongVariant)?,
1192 })
1193 }
1194}
1195
1196impl From<MinaBaseAccountUpdatePreconditionsStableV1> for GraphQLPreconditions {
1197 fn from(value: MinaBaseAccountUpdatePreconditionsStableV1) -> Self {
1198 Self {
1199 network: GraphQLPreconditionsNetwork::from(value.network),
1200 account: GraphQLPreconditionsAccount::from(value.account),
1201 valid_while: if let MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Check(v) =
1202 value.valid_while
1203 {
1204 Some(GraphQLPreconditionsNetworkBounds {
1205 upper: v.upper.as_u32().to_string(),
1206 lower: v.lower.as_u32().to_string(),
1207 })
1208 } else {
1209 None
1210 },
1211 }
1212 }
1213}
1214
1215impl TryFrom<InputGraphQLPreconditions> for MinaBaseAccountUpdatePreconditionsStableV1 {
1216 type Error = ConversionError;
1217 fn try_from(value: InputGraphQLPreconditions) -> Result<Self, Self::Error> {
1218 Ok(Self {
1219 network: value.network.try_into()?,
1220 account: value.account.try_into()?,
1221 valid_while: if let Some(v) = value.valid_while {
1222 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Check(
1223 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlotA {
1224 upper: MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1225 (v.upper.parse::<u32>()?).into(),
1226 ),
1227 lower: MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1228 (v.lower.parse::<u32>()?).into(),
1229 ),
1230 },
1231 )
1232 } else {
1233 MinaBaseZkappPreconditionProtocolStateStableV1GlobalSlot::Ignore
1234 },
1235 })
1236 }
1237}
1238
1239impl TryFrom<MinaBaseVerificationKeyWireStableV1> for GraphQLVerificationKey {
1240 type Error = ConversionError;
1241
1242 fn try_from(value: MinaBaseVerificationKeyWireStableV1) -> Result<Self, Self::Error> {
1243 Ok(Self {
1244 data: value.to_base64()?,
1245 hash: VerificationKey::try_from(&value)
1246 .map_err(|_| ConversionError::InvalidBigInt)?
1247 .hash()
1248 .to_decimal(),
1249 })
1250 }
1251}
1252
1253impl TryFrom<InputGraphQLVerificationKey> for MinaBaseVerificationKeyWireStableV1 {
1254 type Error = ConversionError;
1255
1256 fn try_from(value: InputGraphQLVerificationKey) -> Result<Self, Self::Error> {
1257 Ok(Self::from_base64(&value.data)?)
1258 }
1259}
1260
1261impl TryFrom<MinaBaseAccountUpdateUpdateStableV1> for GraphQLAccountUpdateUpdate {
1262 type Error = ConversionError;
1263
1264 fn try_from(value: MinaBaseAccountUpdateUpdateStableV1) -> Result<Self, Self::Error> {
1265 Ok(Self {
1266 app_state: value
1267 .app_state
1268 .0
1269 .into_iter()
1270 .map(|v| {
1271 if let MinaBaseAccountUpdateUpdateStableV1AppStateA::Set(value) = v {
1272 Some(value.to_decimal())
1273 } else {
1274 None
1275 }
1276 })
1277 .collect(),
1278 delegate: if let MinaBaseAccountUpdateUpdateStableV1Delegate::Set(v) = value.delegate {
1279 Some(v.to_string())
1280 } else {
1281 None
1282 },
1283 verification_key: if let MinaBaseAccountUpdateUpdateStableV1VerificationKey::Set(v) =
1284 value.verification_key
1285 {
1286 Some(GraphQLVerificationKey::try_from(*v)?)
1287 } else {
1288 None
1289 },
1290 permissions: if let MinaBaseAccountUpdateUpdateStableV1Permissions::Set(v) =
1291 value.permissions
1292 {
1293 Some(GraphQLAccountUpdateUpdatePermissions::from(*v))
1294 } else {
1295 None
1296 },
1297 zkapp_uri: if let MinaBaseAccountUpdateUpdateStableV1ZkappUri::Set(v) = value.zkapp_uri
1298 {
1299 Some(v.to_string())
1300 } else {
1301 None
1302 },
1303 token_symbol: if let MinaBaseAccountUpdateUpdateStableV1TokenSymbol::Set(v) =
1304 value.token_symbol
1305 {
1306 Some(v.to_string())
1307 } else {
1308 None
1309 },
1310 timing: if let MinaBaseAccountUpdateUpdateStableV1Timing::Set(v) = value.timing {
1311 Some(GraphQLTiming::from(*v))
1312 } else {
1313 None
1314 },
1315 voting_for: if let MinaBaseAccountUpdateUpdateStableV1VotingFor::Set(v) =
1316 value.voting_for
1317 {
1318 Some(v.to_string())
1319 } else {
1320 None
1321 },
1322 })
1323 }
1324}
1325
1326impl TryFrom<InputGraphQLAccountUpdateUpdate> for MinaBaseAccountUpdateUpdateStableV1 {
1327 type Error = ConversionError;
1328 fn try_from(value: InputGraphQLAccountUpdateUpdate) -> Result<Self, Self::Error> {
1329 let app_state: Vec<_> = value
1330 .app_state
1331 .iter()
1332 .map(|v| {
1333 if let Some(v) = v {
1334 Ok(MinaBaseAccountUpdateUpdateStableV1AppStateA::Set(
1335 BigInt::from_decimal(v)?,
1336 ))
1337 } else {
1338 Ok(MinaBaseAccountUpdateUpdateStableV1AppStateA::Keep)
1339 }
1340 })
1341 .collect::<Result<Vec<_>, ConversionError>>()?;
1342 Ok(Self {
1343 app_state: PaddedSeq(
1344 app_state
1345 .try_into()
1346 .map_err(|_| ConversionError::InvalidLength)?,
1347 ),
1348 delegate: if let Some(delegate) = value.delegate {
1349 MinaBaseAccountUpdateUpdateStableV1Delegate::Set(
1350 AccountPublicKey::from_str(&delegate)?.into(),
1351 )
1352 } else {
1353 MinaBaseAccountUpdateUpdateStableV1Delegate::Keep
1354 },
1355 verification_key: if let Some(vk) = value.verification_key {
1356 MinaBaseAccountUpdateUpdateStableV1VerificationKey::Set(Box::new(
1357 MinaBaseVerificationKeyWireStableV1::try_from(vk)?,
1358 ))
1359 } else {
1360 MinaBaseAccountUpdateUpdateStableV1VerificationKey::Keep
1361 },
1362 permissions: if let Some(permissions) = value.permissions {
1363 MinaBaseAccountUpdateUpdateStableV1Permissions::Set(Box::new(
1364 MinaBasePermissionsStableV2::try_from(permissions)?,
1365 ))
1366 } else {
1367 MinaBaseAccountUpdateUpdateStableV1Permissions::Keep
1368 },
1369 zkapp_uri: if let Some(zkapp_uri) = value.zkapp_uri {
1370 MinaBaseAccountUpdateUpdateStableV1ZkappUri::Set(ZkAppUri::from(zkapp_uri.as_str()))
1371 } else {
1372 MinaBaseAccountUpdateUpdateStableV1ZkappUri::Keep
1373 },
1374 token_symbol: if let Some(token_symbol) = value.token_symbol {
1375 MinaBaseAccountUpdateUpdateStableV1TokenSymbol::Set(TokenSymbol::from(
1376 token_symbol.as_str(),
1377 ))
1378 } else {
1379 MinaBaseAccountUpdateUpdateStableV1TokenSymbol::Keep
1380 },
1381 timing: if let Some(timing) = value.timing {
1382 MinaBaseAccountUpdateUpdateStableV1Timing::Set(Box::new(
1383 MinaBaseAccountUpdateUpdateTimingInfoStableV1::try_from(timing)?,
1384 ))
1385 } else {
1386 MinaBaseAccountUpdateUpdateStableV1Timing::Keep
1387 },
1388 voting_for: if let Some(voting_for) = value.voting_for {
1389 MinaBaseAccountUpdateUpdateStableV1VotingFor::Set(StateHash::from_str(&voting_for)?)
1390 } else {
1391 MinaBaseAccountUpdateUpdateStableV1VotingFor::Keep
1392 },
1393 })
1394 }
1395}
1396
1397impl From<MinaBaseAccountUpdateFeePayerStableV1> for GraphQLFeePayer {
1398 fn from(value: MinaBaseAccountUpdateFeePayerStableV1) -> Self {
1399 Self {
1400 authorization: value.authorization.to_string(),
1401 body: GraphQLFeePayerBody {
1402 public_key: value.body.public_key.to_string(),
1403 fee: value.body.fee.as_u64().to_string(),
1404 valid_until: value.body.valid_until.map(|v| v.as_u32().to_string()),
1405 nonce: value.body.nonce.to_string(),
1406 },
1407 }
1408 }
1409}
1410
1411impl TryFrom<InputGraphQLFeePayer> for MinaBaseAccountUpdateFeePayerStableV1 {
1412 type Error = ConversionError;
1413
1414 fn try_from(value: InputGraphQLFeePayer) -> Result<Self, Self::Error> {
1415 Ok(Self {
1416 authorization: value.authorization.parse()?,
1417 body: MinaBaseAccountUpdateBodyFeePayerStableV1 {
1418 public_key: value.body.public_key.parse()?,
1419 fee: CurrencyFeeStableV1(value.body.fee.parse::<u64>()?.into()),
1420 valid_until: value
1421 .body
1422 .valid_until
1423 .map(|v| -> Result<_, ConversionError> {
1424 Ok(MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(
1425 v.parse::<u32>()?.into(),
1426 ))
1427 })
1428 .transpose()?,
1429 nonce: value.body.nonce.parse::<u32>()?.into(),
1430 },
1431 })
1432 }
1433}
1434
1435impl TryFrom<MinaBaseAccountUpdateTStableV1> for GraphQLAccountUpdate {
1436 type Error = ConversionError;
1437
1438 fn try_from(value: MinaBaseAccountUpdateTStableV1) -> Result<Self, Self::Error> {
1439 Ok(Self {
1440 body: GraphQLAccountUpdateBody {
1441 public_key: value.body.public_key.to_string(),
1442 token_id: value.body.token_id.to_string(),
1443 use_full_commitment: value.body.use_full_commitment,
1444 increment_nonce: value.body.increment_nonce,
1445 update: GraphQLAccountUpdateUpdate::try_from(value.body.update)?,
1446 balance_change: GraphQLBalanceChange::from(value.body.balance_change),
1447 events: value
1448 .body
1449 .events
1450 .0
1451 .into_iter()
1452 .map(|v| v.into_iter().map(|i| i.to_decimal()).collect())
1453 .collect(),
1454 actions: value
1455 .body
1456 .actions
1457 .0
1458 .into_iter()
1459 .map(|v| v.into_iter().map(|i| i.to_decimal()).collect())
1460 .collect(),
1461 call_data: value.body.call_data.to_decimal(),
1462 call_depth: 0,
1464 preconditions: GraphQLPreconditions::from(value.body.preconditions),
1465 may_use_token: GraphQLMayUseToken::from(value.body.may_use_token),
1466 authorization_kind: GraphQLAuthorizationKind::from(value.body.authorization_kind),
1467 implicit_account_creation_fee: value.body.implicit_account_creation_fee,
1468 },
1469 authorization: GraphQLAuthorization::try_from(value.authorization)?,
1470 })
1471 }
1472}
1473
1474impl TryFrom<InputGraphQLAccountUpdate> for MinaBaseAccountUpdateTStableV1 {
1475 type Error = ConversionError;
1476
1477 fn try_from(value: InputGraphQLAccountUpdate) -> Result<Self, Self::Error> {
1478 Ok(Self {
1479 body: MinaBaseAccountUpdateBodyStableV1 {
1480 public_key: value.body.public_key.parse()?,
1481 token_id: value.body.token_id.parse()?,
1482 update: value.body.update.try_into()?,
1483 balance_change: value.body.balance_change.try_into()?,
1484 increment_nonce: value.body.increment_nonce,
1485 events: MinaBaseAccountUpdateBodyEventsStableV1(
1486 value
1487 .body
1488 .events
1489 .into_iter()
1490 .map(|v| {
1491 v.into_iter()
1492 .map(|i| BigInt::from_decimal(&i).map_err(ConversionError::from))
1493 .collect::<Result<_, _>>()
1494 })
1495 .collect::<Result<_, _>>()?,
1496 ),
1497 actions: MinaBaseAccountUpdateBodyEventsStableV1(
1498 value
1499 .body
1500 .actions
1501 .into_iter()
1502 .map(|v| {
1503 v.into_iter()
1504 .map(|i| BigInt::from_decimal(&i).map_err(ConversionError::from))
1505 .collect::<Result<_, _>>()
1506 })
1507 .collect::<Result<_, _>>()?,
1508 ),
1509 call_data: BigInt::from_decimal(&value.body.call_data)?,
1510 preconditions: value.body.preconditions.try_into()?,
1511 use_full_commitment: value.body.use_full_commitment,
1512 implicit_account_creation_fee: value.body.implicit_account_creation_fee,
1513 may_use_token: value.body.may_use_token.into(),
1514 authorization_kind: value.body.authorization_kind.try_into()?,
1515 },
1516 authorization: value.authorization.try_into()?,
1517 })
1518 }
1519}
1520
1521impl TryFrom<InputGraphQLTiming> for MinaBaseAccountUpdateUpdateTimingInfoStableV1 {
1522 type Error = ConversionError;
1523
1524 fn try_from(value: InputGraphQLTiming) -> Result<Self, Self::Error> {
1525 let cliff_time: u32 = value.cliff_time.try_into()?;
1526 let vesting_period: u32 = value.vesting_period.try_into()?;
1527 Ok(Self {
1528 initial_minimum_balance: CurrencyBalanceStableV1(CurrencyAmountStableV1(
1529 value.initial_minimum_balance.parse::<u64>()?.into(),
1530 )),
1531 cliff_time: MinaNumbersGlobalSlotSinceGenesisMStableV1::SinceGenesis(cliff_time.into()),
1532 cliff_amount: CurrencyAmountStableV1(value.cliff_amount.parse::<u64>()?.into()),
1533 vesting_period: MinaNumbersGlobalSlotSpanStableV1::GlobalSlotSpan(
1534 vesting_period.into(),
1535 ),
1536 vesting_increment: CurrencyAmountStableV1(
1537 value.vesting_increment.parse::<u64>()?.into(),
1538 ),
1539 })
1540 }
1541}
1542
1543#[cfg(test)]
1544mod test {
1545 use std::str::FromStr;
1546
1547 use mina_p2p_messages::{
1548 binprot::BinProtRead,
1549 v2::{
1550 MinaBaseSignedCommandMemoStableV1, MinaBaseUserCommandStableV2,
1551 MinaBaseZkappCommandTStableV1WireStableV1,
1552 },
1553 };
1554
1555 use super::*;
1556
1557 #[test]
1558 fn test_empty_memo() {
1559 use ledger::scan_state::transaction_logic::Memo;
1560
1561 let expected = "E4YM2vTHhWEg66xpj52JErHUBU4pZ1yageL4TVDDpTTSsv8mK6YaH";
1562 let empty_memo = Memo::from_str("").unwrap();
1563 let mina_empty_memo = MinaBaseSignedCommandMemoStableV1::from(&empty_memo);
1564 assert_eq!(mina_empty_memo.to_base58check(), expected);
1565 let empty_memo = Memo::empty();
1566 let mina_empty_memo = MinaBaseSignedCommandMemoStableV1::from(&empty_memo);
1567 assert_eq!(mina_empty_memo.to_base58check(), expected);
1568 }
1569
1570 #[test]
1571 fn test_parse_zkapp_bug_1464_no_proof_nor_signature() {
1572 let input = create_input_graphql_zkapp_bug_1464();
1573 let _converted: MinaBaseUserCommandStableV2 = input
1574 .zkapp_command
1575 .try_into()
1576 .expect("Failed to parse input");
1577 }
1578
1579 #[test]
1580 fn test_zkapp_from_input() {
1581 let bytes = include_bytes!("../../../../tests/files/zkapps/valid_zkapp.bin");
1582 let zkapp =
1583 MinaBaseZkappCommandTStableV1WireStableV1::binprot_read(&mut bytes.as_slice()).unwrap();
1584
1585 let serialized_valid = serde_json::to_string_pretty(&zkapp).unwrap();
1586
1587 std::fs::write("zkapp_valid.json", &serialized_valid).unwrap();
1588
1589 let from_input = create_input_graphql_zkapp();
1590 let converted: MinaBaseUserCommandStableV2 = from_input.zkapp_command.try_into().unwrap();
1591 if let MinaBaseUserCommandStableV2::ZkappCommand(zkapp_cmd) = converted {
1592 let serialized_converted = serde_json::to_string_pretty(&zkapp_cmd).unwrap();
1593 std::fs::write("zkapp_converted.json", &serialized_converted).unwrap();
1594 assert_eq!(serialized_valid, serialized_converted);
1595 } else {
1596 unreachable!()
1597 }
1598 }
1599
1600 #[test]
1601 fn test_authorization_kind() {
1602 let kind = InputGraphQLAuthorizationKind {
1603 is_signed: false,
1604 is_proved: true,
1605 verification_key_hash: Some(
1606 "19951435866906059835892103359374709356309230417850637795098911039647240505427"
1607 .to_string(),
1608 ),
1609 };
1610 let converted: Result<MinaBaseAccountUpdateAuthorizationKindStableV1, ConversionError> =
1611 kind.try_into();
1612
1613 assert!(converted.is_ok());
1614 }
1615
1616 #[test]
1617 fn test_authorization_proof() {
1618 let proof = InputGraphQLAuthorization {
1619 signature: None,
1620 proof: Some(
1621 include_str!("../../../../tests/files/zkapps/proof_string.txt").to_string(),
1622 ),
1623 };
1624 let converted: Result<MinaBaseControlStableV2, _> = proof.try_into();
1625 assert!(converted.is_ok());
1626
1627 let proof = InputGraphQLAuthorization {
1628 signature: None,
1629 proof: None,
1630 };
1631 let converted: MinaBaseControlStableV2 =
1632 proof.try_into().expect("Error parsing None given auth");
1633
1634 assert_eq!(converted, MinaBaseControlStableV2::NoneGiven);
1635 }
1636
1637 fn create_input_graphql_zkapp() -> InputGraphQLZkapp {
1638 InputGraphQLZkapp {
1639 zkapp_command: InputGraphQLZkappCommand {
1640 memo: Some("E4YM2vTHhWEg66xpj52JErHUBU4pZ1yageL4TVDDpTTSsv8mK6YaH".to_string()),
1641 fee_payer: InputGraphQLFeePayer {
1642 body: InputGraphQLFeePayerBody {
1643 public_key: "B62qpD75xH5R19wxZG2uz8whNsHPTioVoYcPV3zfjjSbzTmaHQHKKEV".to_string(),
1644 fee: "117000000".to_string(),
1645 valid_until: None,
1646 nonce: "1128".to_string(),
1647 },
1648 authorization: "7mX5Lwu2bdnJPc4DJu7CkwTSR5behoKH8yZh7myCGgYfib5Sq3dfgPQY6LcXdrpQma1NvoLC5i7HLFEQZTnkBFcn96TP57JF".to_string(),
1649 },
1650 account_updates: vec![
1651 InputGraphQLAccountUpdate {
1652 body: InputGraphQLAccountUpdateBody {
1653 call_depth: 0,
1654 public_key: "B62qpD75xH5R19wxZG2uz8whNsHPTioVoYcPV3zfjjSbzTmaHQHKKEV".to_string(),
1655 token_id: "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf".to_string(),
1656 update: InputGraphQLAccountUpdateUpdate {
1657 app_state: vec![
1658 None,
1659 None,
1660 None,
1661 None,
1662 None,
1663 None,
1664 None,
1665 None,
1666 ],
1667 delegate: None,
1668 verification_key: None,
1669 permissions: None,
1670 zkapp_uri: None,
1671 token_symbol: None,
1672 timing: None,
1673 voting_for: None,
1674 },
1675 balance_change: InputGraphQLBalanceChange {
1676 magnitude: "1000000000".to_string(),
1677 sgn: "Negative".to_string(),
1678 },
1679 increment_nonce: false,
1680 events: vec![],
1681 actions: vec![],
1682 call_data: "0".to_string(),
1683 preconditions: InputGraphQLPreconditions {
1684 network: InputGraphQLPreconditionsNetwork {
1685 snarked_ledger_hash: None,
1686 blockchain_length: None,
1687 min_window_density: None,
1688 total_currency: None,
1689 global_slot_since_genesis: None,
1690 staking_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1691 ledger: InputGraphQLPreconditionsNetworkLedger {
1692 hash: None,
1693 total_currency: None,
1694 },
1695 seed: None,
1696 start_checkpoint: None,
1697 lock_checkpoint: None,
1698 epoch_length: None,
1699 },
1700 next_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1701 ledger: InputGraphQLPreconditionsNetworkLedger {
1702 hash: None,
1703 total_currency: None,
1704 },
1705 seed: None,
1706 start_checkpoint: None,
1707 lock_checkpoint: None,
1708 epoch_length: None,
1709 },
1710 },
1711 account: InputGraphQLPreconditionsAccount {
1712 balance: None,
1713 nonce: None,
1714 receipt_chain_hash: None,
1715 delegate: None,
1716 state: vec![
1717 None, None, None, None, None, None, None, None
1718 ],
1719 action_state: None,
1720 proved_state: None,
1721 is_new: None,
1722 },
1723 valid_while: None,
1724 },
1725 use_full_commitment: true,
1726 implicit_account_creation_fee: false,
1727 may_use_token: InputGraphQLMayUseToken {
1728 parents_own_token: false,
1729 inherit_from_parent: false,
1730 },
1731 authorization_kind: InputGraphQLAuthorizationKind {
1732 is_signed: true,
1733 is_proved: false,
1734 verification_key_hash: None,
1735 },
1736 },
1737 authorization: InputGraphQLAuthorization {
1738 proof: None,
1739 signature: Some("7mX5Lwu2bdnJPc4DJu7CkwTSR5behoKH8yZh7myCGgYfib5Sq3dfgPQY6LcXdrpQma1NvoLC5i7HLFEQZTnkBFcn96TP57JF".to_string()),
1740 },
1741 },
1742 InputGraphQLAccountUpdate {
1743 body: InputGraphQLAccountUpdateBody {
1744 call_depth: 0,
1745 public_key: "B62qqKAQh8M61uvuw3tjJsmRgsEvzRm84Nc9MwXTF3zoqFRZ86rV8qk".to_string(),
1746 token_id: "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf".to_string(),
1747 update: InputGraphQLAccountUpdateUpdate {
1748 app_state: vec![
1749 Some("1".to_string()),
1750 Some("0".to_string()),
1751 Some("0".to_string()),
1752 Some("0".to_string()),
1753 Some("0".to_string()),
1754 Some("0".to_string()),
1755 Some("0".to_string()),
1756 Some("0".to_string()),
1757 ],
1758 delegate: None,
1759 verification_key: Some(InputGraphQLVerificationKey {
1760 data: "AACcenc1yLdGBm4xtUN1dpModROI0zovuy5rz2a94vfdBgG1C75BqviU4vw6JUYqODF8n9ivtfeU5s9PcpEGIP0htil2mfx8v2DB5RuNQ7VxJWkha0TSnJJsOl0FxhjldBbOY3tUZzZxHpPhHOKHz/ZAXRYFIsf2x+7boXC0iPurEX9VcnaJIq+YxxmnSfeYYxHkjxO9lrDBqjXzd5AHMnYyjTPC69B+5In7AOGS6R+A/g3/aR/MKDa4eDVrnsF9Oy/Ay8ahic2sSAZvtn08MdRyk/jm2cLlJbeAAad6Xyz/H9l7JrkbVwDMMPxvHVHs27tNoJCzIlrRzB7pg3ju9aQOu4h3thDr+WSgFQWKvcRPeL7f3TFjIr8WZ2457RgMcTwXwORKbqJCcyKVNOE+FlNwVkOKER+WIpC0OlgGuayPFwQQkbb91jaRlJvahfwkbF2+AJmDnavmNpop9T+/Xak1adXIrsRPeOjC+qIKxIbGimoMOoYzYlevKA80LnJ7HC0IxR+yNLvoSYxDDPNRD+OCCxk5lM2h8IDUiCNWH4FZNJ+doiigKjyZlu/xZ7jHcX7qibu/32KFTX85DPSkQM8dAEkH+vlkHmyXGLF4+xOVKeM0ihV5OEQrOABcgfTkbRsyxNInUBh0WiQyALE2ctjvkRCiE2P24bjFA8SgFmTM7gAKR89XcqLS/NP7lwCEej/L8q8R7sKGMCXmgFYluWH4JBSPDgvMxScfjFS33oBNb7po8cLnAORzohXoYTSgztklD0mKn6EegLbkLtwwr9ObsLz3m7fp/3wkNWFRkY5xzSZN1VybbQbmpyQNCpxd/kdDsvlszqlowkyC8HnKbhnvE0Mrz3ZIk4vSs/UGBSXAoESFCFCPcTq11TCOhE5rumMJErv5LusDHJgrBtQUMibLU9A1YbF7SPDAR2QZd0yx3waAC2F3xF+U682SOKF7oCZl2OICysRHqH+rZ604UfdGG0zWRuP2yg6kfGwcGQbO1ql40WrWTiFhbxxdKC7Gbz4y9Sb7q5EsPt6Z1AIn34/nXB/IWfC0gg/OgfPQTR7uxiTo2OOwjHni1f4KhT4rEmDAQn6ty6/ZRKHPWjUaAREbEw3tC36fI09hCYjjVTEmMAFTApk/tMUu0tC9Dt/vfDgXAlDJBwN5Y2Pt60qWY92skizVcWyWBxp5A8e4cVu3iToxOGUbSHzawovjubcH7qWjIZoghZJ16QB1c0ryiAfHB48OHhs2p/JZWz8Dp7kfcPkeg2Of2NbupJlNVMLIH4IGWaPAscBRkZ+F4oLqOhJ5as7fAzzU8PQdeZi0YgssGDJVmNEHP61I16KZNcxQqR0EUVwhyMmYmpVjvtfhHi/6I3TgYCmfnm6GL2sN144vMWg/gJ+p9a4GcEA0+gK3oCcKcwkq5rm+1Oxo9LWLp92Bdxq3iqfoIFmJ/ANGSbHF8StVmlVsP8zA+xuHylyiww/Lercce7cq0YA5PtYS3ge9IDYwXckBUXb5ikD3alrrv5mvMu6itB7ix2f8lbiF9Fkmc4Bk2ycIWXJDCuBN+2sTFqzUeoT6xY8XWaOcnDvqOgSm/CCSv38umiOE2jEpsKYxhRc6W70UJkrzd3hr2DiSF1I2B+krpUVK1GeOdCLC5sl7YPzk+pF8183uI9wse6UTlqIiroKqsggzLBy/IjAfxS0BxFy5zywXqp+NogFkoTEJmR5MaqOkPfap+OsD1lGScY6+X4WW/HqCWrmA3ZTqDGngQMTGXLCtl6IS/cQpihS1NRbNqOtKTaCB9COQu0oz6RivBlywuaj3MKUdmbQ2gVDj+SGQItCNaXawyPSBjB9VT+68SoJVySQsYPCuEZCb0V/40n/a7RAbyrnNjP+2HwD7p27Pl1RSzqq35xiPdnycD1UeEPLpx/ON65mYCkn+KLQZmkqPio+vA2KmJngWTx+ol4rVFimGm76VT0xCFDsu2K0YX0yoLNH4u2XfmT9NR8gGfkVRCnnNjlbgHQmEwC75+GmEJ5DjD3d+s6IXTQ60MHvxbTHHlnfmPbgKn2SAI0uVoewKC9GyK6dSaboLw3C48jl0E2kyc+7umhCk3kEeWmt//GSjRNhoq+B+mynXiOtgFs/Am2v1TBjSb+6tcijsf5tFJmeGxlCjJnTdNWBkSHpMoo6OFkkpA6/FBAUHLSM7Yv8oYyd0GtwF5cCwQ6aRTbl9oG/mUn5Q92OnDMQcUjpgEho0Dcp2OqZyyxqQSPrbIIZZQrS2HkxBgjcfcSTuSHo7ONqlRjLUpO5yS95VLGXBLLHuCiIMGT+DW6DoJRtRIS+JieVWBoX0YsWgYInXrVlWUv6gDng5AyVFkUIFwZk7/3mVAgvXO83ArVKA4S747jT60w5bgV4Jy55slDM=".to_string(),
1761 hash: "11640126627177324946637007967436400725357874055180801746732941023691529117236".to_string(),
1762 }),
1763 permissions: Some(InputGraphQLAccountUpdateUpdatePermissions {
1764 edit_state: "Proof".to_string(),
1765 access: "Proof".to_string(),
1766 send: "Proof".to_string(),
1767 receive: "Proof".to_string(),
1768 set_delegate: "Proof".to_string(),
1769 set_permissions: "Proof".to_string(),
1770 set_verification_key: InputGraphQLSetVerificationKeyPermissions {
1771 auth: "Proof".to_string(),
1772 txn_version: "3".to_string(),
1773 },
1774 set_zkapp_uri: "Proof".to_string(),
1775 edit_action_state: "Proof".to_string(),
1776 set_token_symbol: "Proof".to_string(),
1777 set_timing: "Proof".to_string(),
1778 set_voting_for: "Proof".to_string(),
1779 increment_nonce: "Proof".to_string(),
1780 }),
1781 zkapp_uri: None,
1782 token_symbol: None,
1783 timing: None,
1784 voting_for: None,
1785 },
1786 balance_change: InputGraphQLBalanceChange {
1787 magnitude: "0".to_string(),
1788 sgn: "Positive".to_string(),
1789 },
1790 increment_nonce: true,
1791 events: vec![],
1792 actions: vec![],
1793 call_data: "0".to_string(),
1794 preconditions: InputGraphQLPreconditions {
1795 network: InputGraphQLPreconditionsNetwork {
1796 snarked_ledger_hash: None,
1797 blockchain_length: None,
1798 min_window_density: None,
1799 total_currency: None,
1800 global_slot_since_genesis: None,
1801 staking_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1802 ledger: InputGraphQLPreconditionsNetworkLedger {
1803 hash: None,
1804 total_currency: None,
1805 },
1806 seed: None,
1807 start_checkpoint: None,
1808 lock_checkpoint: None,
1809 epoch_length: None,
1810 },
1811 next_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1812 ledger: InputGraphQLPreconditionsNetworkLedger {
1813 hash: None,
1814 total_currency: None,
1815 },
1816 seed: None,
1817 start_checkpoint: None,
1818 lock_checkpoint: None,
1819 epoch_length: None,
1820 },
1821 },
1822 account: InputGraphQLPreconditionsAccount {
1823 balance: None,
1824 nonce: Some(InputGraphQLPreconditionsNetworkBounds {
1825 upper: "0".to_string(),
1826 lower: "0".to_string(),
1827 }),
1828 receipt_chain_hash: None,
1829 delegate: None,
1830 state: vec![
1831 None, None, None, None, None, None, None, None
1832 ],
1833 action_state: None,
1834 proved_state: Some(false),
1835 is_new: None,
1836 },
1837 valid_while: None,
1838 },
1839 use_full_commitment: false,
1840 implicit_account_creation_fee: false,
1841 may_use_token: InputGraphQLMayUseToken {
1842 parents_own_token: false,
1843 inherit_from_parent: false,
1844 },
1845 authorization_kind: InputGraphQLAuthorizationKind {
1846 is_signed: true,
1847 is_proved: false,
1848 verification_key_hash: None,
1849 },
1850 },
1851 authorization: InputGraphQLAuthorization {
1852 proof: None,
1853 signature: Some("7mXFnDxZBE5iXBfw9LRPXST3sSodXAdTJSWFqX3hBoDA3wv5s2s9TLMDCXgatMvMH4bDttAFyJuezWmbSA81FXeMFZgqcxtt".to_string()),
1854 },
1855 },
1856 ],
1857 },
1858 }
1859 }
1860
1861 fn create_input_graphql_zkapp_bug_1464() -> InputGraphQLZkapp {
1862 InputGraphQLZkapp {
1863 zkapp_command: InputGraphQLZkappCommand {
1864 memo: Some("E4YdMZb5VHHE51HPFPs1zUHnyus1q7RW61tWq1F4FNYrp5FKtKZMh".to_string()),
1865 fee_payer: InputGraphQLFeePayer {
1866 body: InputGraphQLFeePayerBody {
1867 public_key: "B62qmGcEhZsZ2EMh2EzRXDJEmaD9PUJcW5xdNq2im2xNVuX2bsEPjoj".to_string(),
1868 fee: "200000000".to_string(),
1869 valid_until: None,
1870 nonce: "250".to_string(),
1871 },
1872 authorization: "7mXMa44TWfDGtQmsfGtkRogZVzGVYqosP6qkXCBApsjoZ2ye2Y5AL2VWzp7m5CxkTjZhcoqtDVJkiQRm38tAmQdhpTTsSEr6".to_string(),
1873 },
1874 account_updates: vec![
1875 InputGraphQLAccountUpdate {
1876 body: InputGraphQLAccountUpdateBody {
1877 call_depth: 0,
1878 public_key: "B62qmGcEhZsZ2EMh2EzRXDJEmaD9PUJcW5xdNq2im2xNVuX2bsEPjoj".to_string(),
1879 token_id: "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf".to_string(),
1880 update: InputGraphQLAccountUpdateUpdate {
1881 app_state: vec![
1882 None,
1883 None,
1884 None,
1885 None,
1886 None,
1887 None,
1888 None,
1889 None,
1890 ],
1891 delegate: None,
1892 verification_key: None,
1893 permissions: None,
1894 zkapp_uri: None,
1895 token_symbol: None,
1896 timing: None,
1897 voting_for: None,
1898 },
1899 balance_change: InputGraphQLBalanceChange {
1900 magnitude: "0".to_string(),
1901 sgn: "Positive".to_string(),
1902 },
1903 increment_nonce: false,
1904 events: vec![vec![
1905 "852".to_owned(),
1906 "993".to_owned(),
1907 "540".to_owned(),
1908 "951".to_owned(),
1909 "340".to_owned()
1910 ]],
1911 actions: vec![],
1912 call_data: "0".to_string(),
1913 preconditions: InputGraphQLPreconditions {
1914 network: InputGraphQLPreconditionsNetwork {
1915 snarked_ledger_hash: None,
1916 blockchain_length: None,
1917 min_window_density: None,
1918 total_currency: None,
1919 global_slot_since_genesis: None,
1920 staking_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1921 ledger: InputGraphQLPreconditionsNetworkLedger {
1922 hash: None,
1923 total_currency: None,
1924 },
1925 seed: None,
1926 start_checkpoint: None,
1927 lock_checkpoint: None,
1928 epoch_length: None,
1929 },
1930 next_epoch_data: InputGraphQLPreconditionsNetworkEpochData {
1931 ledger: InputGraphQLPreconditionsNetworkLedger {
1932 hash: None,
1933 total_currency: None,
1934 },
1935 seed: None,
1936 start_checkpoint: None,
1937 lock_checkpoint: None,
1938 epoch_length: None,
1939 },
1940 },
1941 account: InputGraphQLPreconditionsAccount {
1942 balance: None,
1943 nonce: None,
1944 receipt_chain_hash: None,
1945 delegate: None,
1946 state: vec![
1947 None, None, None, None, None, None, None, None
1948 ],
1949 action_state: None,
1950 proved_state: None,
1951 is_new: None,
1952 },
1953 valid_while: None,
1954 },
1955 use_full_commitment: false,
1956 implicit_account_creation_fee: false,
1957 may_use_token: InputGraphQLMayUseToken {
1958 parents_own_token: false,
1959 inherit_from_parent: false,
1960 },
1961 authorization_kind: InputGraphQLAuthorizationKind {
1962 is_signed: false,
1963 is_proved: false,
1964 verification_key_hash: Some("3392518251768960475377392625298437850623664973002200885669375116181514017494".parse().unwrap()),
1965 },
1966 },
1967 authorization: InputGraphQLAuthorization {
1968 proof: None,
1969 signature: None
1970 },
1971 },
1972 ],
1973 },
1974 }
1975 }
1976
1977 #[test]
1978 pub fn test_bigint_to_decimal() {
1979 let bigint = BigInt::from_decimal("1").unwrap();
1980 let decimal = serde_json::to_string(&bigint).unwrap();
1981 assert_eq!(
1982 decimal,
1983 "\"0x0000000000000000000000000000000000000000000000000000000000000001\"".to_string()
1984 );
1985 }
1986}