1use {
2 crate::{StoredExtendedRewards, StoredTransactionError, StoredTransactionStatusMeta},
3 solana_account_decoder::parse_token::{UiTokenAmount, real_number_string_trimmed},
4 solana_hash::{HASH_BYTES, Hash},
5 solana_instruction::error::InstructionError,
6 solana_message::{
7 MessageHeader, VersionedMessage,
8 compiled_instruction::CompiledInstruction,
9 legacy::Message as LegacyMessage,
10 v0::{self, LoadedAddresses, MessageAddressTableLookup},
11 v1,
12 },
13 solana_pubkey::Pubkey,
14 solana_signature::Signature,
15 solana_transaction::{Transaction, versioned::VersionedTransaction},
16 solana_transaction_context::transaction::TransactionReturnData,
17 solana_transaction_error::TransactionError,
18 solana_transaction_status::{
19 ConfirmedBlock, EntrySummary, InnerInstruction, InnerInstructions, Reward, RewardType,
20 RewardsAndNumPartitions, TransactionByAddrInfo, TransactionStatusMeta,
21 TransactionTokenBalance, TransactionWithStatusMeta, VersionedConfirmedBlock,
22 VersionedTransactionWithStatusMeta,
23 },
24 std::{
25 convert::{TryFrom, TryInto},
26 str::FromStr,
27 },
28 wincode::ReadError,
29};
30
31pub mod generated {
32 include!(concat!(
33 env!("OUT_DIR"),
34 "/solana.storage.confirmed_block.rs"
35 ));
36}
37
38pub mod tx_by_addr {
39 include!(concat!(
40 env!("OUT_DIR"),
41 "/solana.storage.transaction_by_addr.rs"
42 ));
43}
44
45pub mod entries {
46 include!(concat!(env!("OUT_DIR"), "/solana.storage.entries.rs"));
47}
48
49#[derive(Debug, thiserror::Error)]
50#[error("failed to decode {bytes:?}: {source}")]
51pub struct DecodeError {
52 pub bytes: Vec<u8>,
53 #[source]
54 pub source: ReadError,
55}
56
57impl From<Vec<Reward>> for generated::Rewards {
58 fn from(rewards: Vec<Reward>) -> Self {
59 Self {
60 rewards: rewards.into_iter().map(|r| r.into()).collect(),
61 num_partitions: None,
62 }
63 }
64}
65
66impl From<RewardsAndNumPartitions> for generated::Rewards {
67 fn from(input: RewardsAndNumPartitions) -> Self {
68 Self {
69 rewards: input.rewards.into_iter().map(|r| r.into()).collect(),
70 num_partitions: input.num_partitions.map(|n| n.into()),
71 }
72 }
73}
74
75impl From<generated::Rewards> for Vec<Reward> {
76 fn from(rewards: generated::Rewards) -> Self {
77 rewards.rewards.into_iter().map(|r| r.into()).collect()
78 }
79}
80
81impl From<generated::Rewards> for RewardsAndNumPartitions {
82 fn from(rewards: generated::Rewards) -> Self {
83 Self {
84 rewards: rewards.rewards.into_iter().map(|r| r.into()).collect(),
85 num_partitions: rewards
86 .num_partitions
87 .map(|generated::NumPartitions { num_partitions }| num_partitions),
88 }
89 }
90}
91
92impl From<StoredExtendedRewards> for generated::Rewards {
93 fn from(rewards: StoredExtendedRewards) -> Self {
94 Self {
95 rewards: rewards
96 .into_iter()
97 .map(|r| {
98 let r: Reward = r.into();
99 r.into()
100 })
101 .collect(),
102 num_partitions: None,
103 }
104 }
105}
106
107impl From<generated::Rewards> for StoredExtendedRewards {
108 fn from(rewards: generated::Rewards) -> Self {
109 rewards
110 .rewards
111 .into_iter()
112 .map(|r| {
113 let r: Reward = r.into();
114 r.into()
115 })
116 .collect()
117 }
118}
119
120impl From<Reward> for generated::Reward {
121 fn from(reward: Reward) -> Self {
122 Self {
123 pubkey: reward.pubkey,
124 lamports: reward.lamports,
125 post_balance: reward.post_balance,
126 reward_type: match reward.reward_type {
127 None => generated::RewardType::Unspecified,
128 Some(RewardType::Fee) => generated::RewardType::Fee,
129 Some(RewardType::Rent) => generated::RewardType::Rent,
130 Some(RewardType::Staking) => generated::RewardType::Staking,
131 Some(RewardType::Voting) => generated::RewardType::Voting,
132 Some(RewardType::DeactivatedStake) => generated::RewardType::DeactivatedStake,
133 } as i32,
134 commission: reward.commission.map(|c| c.to_string()).unwrap_or_default(),
135 commission_bps: reward
136 .commission_bps
137 .map(|bps| bps.to_string())
138 .unwrap_or_default(),
139 }
140 }
141}
142
143impl From<generated::Reward> for Reward {
144 fn from(reward: generated::Reward) -> Self {
145 Self {
146 pubkey: reward.pubkey,
147 lamports: reward.lamports,
148 post_balance: reward.post_balance,
149 reward_type: match reward.reward_type {
150 0 => None,
151 1 => Some(RewardType::Fee),
152 2 => Some(RewardType::Rent),
153 3 => Some(RewardType::Staking),
154 4 => Some(RewardType::Voting),
155 5 => Some(RewardType::DeactivatedStake),
156 _ => None,
157 },
158 commission: reward.commission.parse::<u8>().ok(),
159 commission_bps: reward.commission_bps.parse::<u16>().ok(),
160 }
161 }
162}
163
164impl From<u64> for generated::NumPartitions {
165 fn from(num_partitions: u64) -> Self {
166 Self { num_partitions }
167 }
168}
169
170impl From<VersionedConfirmedBlock> for generated::ConfirmedBlock {
171 fn from(confirmed_block: VersionedConfirmedBlock) -> Self {
172 let VersionedConfirmedBlock {
173 previous_blockhash,
174 blockhash,
175 parent_slot,
176 transactions,
177 rewards,
178 num_partitions,
179 block_time,
180 block_height,
181 } = confirmed_block;
182
183 Self {
184 previous_blockhash,
185 blockhash,
186 parent_slot,
187 transactions: transactions.into_iter().map(|tx| tx.into()).collect(),
188 rewards: rewards.into_iter().map(|r| r.into()).collect(),
189 num_partitions: num_partitions.map(Into::into),
190 block_time: block_time.map(|timestamp| generated::UnixTimestamp { timestamp }),
191 block_height: block_height.map(|block_height| generated::BlockHeight { block_height }),
192 }
193 }
194}
195
196impl TryFrom<generated::ConfirmedBlock> for ConfirmedBlock {
197 type Error = DecodeError;
198 fn try_from(
199 confirmed_block: generated::ConfirmedBlock,
200 ) -> std::result::Result<Self, Self::Error> {
201 let generated::ConfirmedBlock {
202 previous_blockhash,
203 blockhash,
204 parent_slot,
205 transactions,
206 rewards,
207 num_partitions,
208 block_time,
209 block_height,
210 } = confirmed_block;
211
212 Ok(Self {
213 previous_blockhash,
214 blockhash,
215 parent_slot,
216 transactions: transactions
217 .into_iter()
218 .map(|tx| tx.try_into())
219 .collect::<std::result::Result<Vec<_>, Self::Error>>()?,
220 rewards: rewards.into_iter().map(|r| r.into()).collect(),
221 num_partitions: num_partitions
222 .map(|generated::NumPartitions { num_partitions }| num_partitions),
223 block_time: block_time.map(|generated::UnixTimestamp { timestamp }| timestamp),
224 block_height: block_height.map(|generated::BlockHeight { block_height }| block_height),
225 })
226 }
227}
228
229impl From<TransactionWithStatusMeta> for generated::ConfirmedTransaction {
230 fn from(tx_with_meta: TransactionWithStatusMeta) -> Self {
231 match tx_with_meta {
232 TransactionWithStatusMeta::MissingMetadata(transaction) => Self {
233 transaction: Some(generated::Transaction::from(transaction)),
234 meta: None,
235 },
236 TransactionWithStatusMeta::Complete(tx_with_meta) => Self::from(tx_with_meta),
237 }
238 }
239}
240
241impl From<VersionedTransactionWithStatusMeta> for generated::ConfirmedTransaction {
242 fn from(value: VersionedTransactionWithStatusMeta) -> Self {
243 Self {
244 transaction: Some(value.transaction.into()),
245 meta: Some(value.meta.into()),
246 }
247 }
248}
249
250impl TryFrom<generated::ConfirmedTransaction> for TransactionWithStatusMeta {
251 type Error = DecodeError;
252 fn try_from(value: generated::ConfirmedTransaction) -> std::result::Result<Self, Self::Error> {
253 let meta = value.meta.map(|meta| meta.try_into()).transpose()?;
254 let transaction = value.transaction.expect("transaction is required").into();
255 Ok(match meta {
256 Some(meta) => Self::Complete(VersionedTransactionWithStatusMeta { transaction, meta }),
257 None => Self::MissingMetadata(
258 transaction
259 .into_legacy_transaction()
260 .expect("meta is required for versioned transactions"),
261 ),
262 })
263 }
264}
265
266impl From<Transaction> for generated::Transaction {
267 fn from(value: Transaction) -> Self {
268 Self {
269 signatures: value
270 .signatures
271 .into_iter()
272 .map(|signature| <Signature as AsRef<[u8]>>::as_ref(&signature).into())
273 .collect(),
274 message: Some(value.message.into()),
275 }
276 }
277}
278
279impl From<VersionedTransaction> for generated::Transaction {
280 fn from(value: VersionedTransaction) -> Self {
281 Self {
282 signatures: value
283 .signatures
284 .into_iter()
285 .map(|signature| <Signature as AsRef<[u8]>>::as_ref(&signature).into())
286 .collect(),
287 message: Some(value.message.into()),
288 }
289 }
290}
291
292impl From<generated::Transaction> for VersionedTransaction {
293 fn from(value: generated::Transaction) -> Self {
294 Self {
295 signatures: value
296 .signatures
297 .into_iter()
298 .map(Signature::try_from)
299 .collect::<Result<_, _>>()
300 .unwrap(),
301 message: value.message.expect("message is required").into(),
302 }
303 }
304}
305
306impl From<TransactionError> for generated::TransactionError {
307 fn from(value: TransactionError) -> Self {
308 let stored_error = StoredTransactionError::from(value).0;
309 Self { err: stored_error }
310 }
311}
312
313impl From<generated::TransactionError> for TransactionError {
314 fn from(value: generated::TransactionError) -> Self {
315 let stored_error = StoredTransactionError(value.err);
316 stored_error.into()
317 }
318}
319
320impl From<LegacyMessage> for generated::Message {
321 fn from(message: LegacyMessage) -> Self {
322 Self {
323 header: Some(message.header.into()),
324 account_keys: message
325 .account_keys
326 .iter()
327 .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
328 .collect(),
329 recent_blockhash: message.recent_blockhash.to_bytes().into(),
330 instructions: message
331 .instructions
332 .into_iter()
333 .map(|ix| ix.into())
334 .collect(),
335 versioned: false,
336 address_table_lookups: vec![],
337 config: None,
338 }
339 }
340}
341
342impl From<v0::Message> for generated::Message {
343 fn from(message: v0::Message) -> Self {
344 Self {
345 header: Some(message.header.into()),
346 account_keys: message
347 .account_keys
348 .iter()
349 .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
350 .collect(),
351 recent_blockhash: message.recent_blockhash.to_bytes().into(),
352 instructions: message
353 .instructions
354 .into_iter()
355 .map(|ix| ix.into())
356 .collect(),
357 versioned: true,
358 address_table_lookups: message
359 .address_table_lookups
360 .into_iter()
361 .map(|lookup| lookup.into())
362 .collect(),
363 config: None,
364 }
365 }
366}
367
368impl From<v1::Message> for generated::Message {
369 fn from(message: v1::Message) -> Self {
370 Self {
371 header: Some(message.header.into()),
372 account_keys: message
373 .account_keys
374 .iter()
375 .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(key).into())
376 .collect(),
377 recent_blockhash: message.lifetime_specifier.to_bytes().into(),
378 instructions: message
379 .instructions
380 .into_iter()
381 .map(|ix| ix.into())
382 .collect(),
383 versioned: true,
384 address_table_lookups: vec![],
385 config: Some(generated::TransactionConfig {
386 priority_fee: message.config.priority_fee,
387 compute_unit_limit: message.config.compute_unit_limit,
388 loaded_accounts_data_size_limit: message.config.loaded_accounts_data_size_limit,
389 heap_size: message.config.heap_size,
390 }),
391 }
392 }
393}
394
395impl From<VersionedMessage> for generated::Message {
396 fn from(message: VersionedMessage) -> Self {
397 match message {
398 VersionedMessage::Legacy(message) => Self::from(message),
399 VersionedMessage::V0(message) => Self::from(message),
400 VersionedMessage::V1(message) => Self::from(message),
401 }
402 }
403}
404
405impl From<generated::Message> for VersionedMessage {
406 fn from(value: generated::Message) -> Self {
407 let header = value.header.expect("header is required").into();
408 let account_keys = value
409 .account_keys
410 .into_iter()
411 .map(|key| Pubkey::try_from(key).unwrap())
412 .collect();
413 let recent_blockhash = <[u8; HASH_BYTES]>::try_from(value.recent_blockhash)
414 .map(Hash::new_from_array)
415 .unwrap();
416 let instructions = value.instructions.into_iter().map(|ix| ix.into()).collect();
417
418 if let Some(config) = value.config {
422 return Self::V1(v1::Message {
423 header,
424 config: v1::TransactionConfig {
425 priority_fee: config.priority_fee,
426 compute_unit_limit: config.compute_unit_limit,
427 loaded_accounts_data_size_limit: config.loaded_accounts_data_size_limit,
428 heap_size: config.heap_size,
429 },
430 lifetime_specifier: recent_blockhash,
431 account_keys,
432 instructions,
433 });
434 }
435
436 let address_table_lookups = value
437 .address_table_lookups
438 .into_iter()
439 .map(|lookup| lookup.into())
440 .collect();
441
442 if !value.versioned {
443 Self::Legacy(LegacyMessage {
444 header,
445 account_keys,
446 recent_blockhash,
447 instructions,
448 })
449 } else {
450 Self::V0(v0::Message {
451 header,
452 account_keys,
453 recent_blockhash,
454 instructions,
455 address_table_lookups,
456 })
457 }
458 }
459}
460
461impl From<MessageHeader> for generated::MessageHeader {
462 fn from(value: MessageHeader) -> Self {
463 Self {
464 num_required_signatures: value.num_required_signatures as u32,
465 num_readonly_signed_accounts: value.num_readonly_signed_accounts as u32,
466 num_readonly_unsigned_accounts: value.num_readonly_unsigned_accounts as u32,
467 }
468 }
469}
470
471impl From<generated::MessageHeader> for MessageHeader {
472 fn from(value: generated::MessageHeader) -> Self {
473 Self {
474 num_required_signatures: value.num_required_signatures as u8,
475 num_readonly_signed_accounts: value.num_readonly_signed_accounts as u8,
476 num_readonly_unsigned_accounts: value.num_readonly_unsigned_accounts as u8,
477 }
478 }
479}
480
481impl From<TransactionStatusMeta> for generated::TransactionStatusMeta {
482 fn from(value: TransactionStatusMeta) -> Self {
483 let TransactionStatusMeta {
484 status,
485 fee,
486 pre_balances,
487 post_balances,
488 inner_instructions,
489 log_messages,
490 pre_token_balances,
491 post_token_balances,
492 rewards,
493 loaded_addresses,
494 return_data,
495 compute_units_consumed,
496 cost_units,
497 } = value;
498 let err = match status {
499 Ok(()) => None,
500 Err(err) => Some(generated::TransactionError {
501 err: wincode::serialize(&err).expect("transaction error to serialize to bytes"),
502 }),
503 };
504 let inner_instructions_none = inner_instructions.is_none();
505 let inner_instructions = inner_instructions
506 .unwrap_or_default()
507 .into_iter()
508 .map(|ii| ii.into())
509 .collect();
510 let log_messages_none = log_messages.is_none();
511 let log_messages = log_messages.unwrap_or_default();
512 let pre_token_balances = pre_token_balances
513 .unwrap_or_default()
514 .into_iter()
515 .map(|balance| balance.into())
516 .collect();
517 let post_token_balances = post_token_balances
518 .unwrap_or_default()
519 .into_iter()
520 .map(|balance| balance.into())
521 .collect();
522 let rewards = rewards
523 .unwrap_or_default()
524 .into_iter()
525 .map(|reward| reward.into())
526 .collect();
527 let loaded_writable_addresses = loaded_addresses
528 .writable
529 .into_iter()
530 .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(&key).into())
531 .collect();
532 let loaded_readonly_addresses = loaded_addresses
533 .readonly
534 .into_iter()
535 .map(|key| <Pubkey as AsRef<[u8]>>::as_ref(&key).into())
536 .collect();
537 let return_data_none = return_data.is_none();
538 let return_data = return_data.map(|return_data| return_data.into());
539
540 Self {
541 err,
542 fee,
543 pre_balances,
544 post_balances,
545 inner_instructions,
546 inner_instructions_none,
547 log_messages,
548 log_messages_none,
549 pre_token_balances,
550 post_token_balances,
551 rewards,
552 loaded_writable_addresses,
553 loaded_readonly_addresses,
554 return_data,
555 return_data_none,
556 compute_units_consumed,
557 cost_units,
558 }
559 }
560}
561
562impl From<StoredTransactionStatusMeta> for generated::TransactionStatusMeta {
563 fn from(meta: StoredTransactionStatusMeta) -> Self {
564 let meta: TransactionStatusMeta = meta.into();
565 meta.into()
566 }
567}
568
569impl TryFrom<generated::TransactionStatusMeta> for TransactionStatusMeta {
570 type Error = DecodeError;
571
572 fn try_from(value: generated::TransactionStatusMeta) -> std::result::Result<Self, Self::Error> {
573 let generated::TransactionStatusMeta {
574 err,
575 fee,
576 pre_balances,
577 post_balances,
578 inner_instructions,
579 inner_instructions_none,
580 log_messages,
581 log_messages_none,
582 pre_token_balances,
583 post_token_balances,
584 rewards,
585 loaded_writable_addresses,
586 loaded_readonly_addresses,
587 return_data,
588 return_data_none,
589 compute_units_consumed,
590 cost_units,
591 } = value;
592 let status = match err {
593 None => Ok(()),
594 Some(tx_error) => {
595 let tx_error =
596 wincode::deserialize(&tx_error.err).map_err(|source| DecodeError {
597 bytes: tx_error.err,
598 source,
599 })?;
600 Err(tx_error)
601 }
602 };
603 let inner_instructions = if inner_instructions_none {
604 None
605 } else {
606 Some(
607 inner_instructions
608 .into_iter()
609 .map(|inner| inner.into())
610 .collect(),
611 )
612 };
613 let log_messages = if log_messages_none {
614 None
615 } else {
616 Some(log_messages)
617 };
618 let pre_token_balances = Some(
619 pre_token_balances
620 .into_iter()
621 .map(|balance| balance.into())
622 .collect(),
623 );
624 let post_token_balances = Some(
625 post_token_balances
626 .into_iter()
627 .map(|balance| balance.into())
628 .collect(),
629 );
630 let rewards = Some(rewards.into_iter().map(|reward| reward.into()).collect());
631 let loaded_addresses = LoadedAddresses {
632 writable: loaded_writable_addresses
633 .into_iter()
634 .map(Pubkey::try_from)
635 .collect::<Result<_, _>>()
636 .map_err(|bytes| DecodeError {
637 bytes,
638 source: ReadError::Custom("Invalid writable address"),
639 })?,
640 readonly: loaded_readonly_addresses
641 .into_iter()
642 .map(Pubkey::try_from)
643 .collect::<Result<_, _>>()
644 .map_err(|bytes| DecodeError {
645 bytes,
646 source: ReadError::Custom("Invalid readonly address"),
647 })?,
648 };
649 let return_data = if return_data_none {
650 None
651 } else {
652 return_data.map(|return_data| return_data.into())
653 };
654 Ok(Self {
655 status,
656 fee,
657 pre_balances,
658 post_balances,
659 inner_instructions,
660 log_messages,
661 pre_token_balances,
662 post_token_balances,
663 rewards,
664 loaded_addresses,
665 return_data,
666 compute_units_consumed,
667 cost_units,
668 })
669 }
670}
671
672impl From<InnerInstructions> for generated::InnerInstructions {
673 fn from(value: InnerInstructions) -> Self {
674 Self {
675 index: value.index as u32,
676 instructions: value.instructions.into_iter().map(|i| i.into()).collect(),
677 }
678 }
679}
680
681impl From<generated::InnerInstructions> for InnerInstructions {
682 fn from(value: generated::InnerInstructions) -> Self {
683 Self {
684 index: value.index as u8,
685 instructions: value.instructions.into_iter().map(|i| i.into()).collect(),
686 }
687 }
688}
689
690impl From<TransactionTokenBalance> for generated::TokenBalance {
691 fn from(value: TransactionTokenBalance) -> Self {
692 Self {
693 account_index: value.account_index as u32,
694 mint: value.mint,
695 ui_token_amount: Some(generated::UiTokenAmount {
696 ui_amount: value.ui_token_amount.ui_amount.unwrap_or_default(),
697 decimals: value.ui_token_amount.decimals as u32,
698 amount: value.ui_token_amount.amount,
699 ui_amount_string: value.ui_token_amount.ui_amount_string,
700 }),
701 owner: value.owner,
702 program_id: value.program_id,
703 }
704 }
705}
706
707impl From<generated::TokenBalance> for TransactionTokenBalance {
708 fn from(value: generated::TokenBalance) -> Self {
709 let ui_token_amount = value.ui_token_amount.unwrap_or_default();
710 Self {
711 account_index: value.account_index as u8,
712 mint: value.mint,
713 ui_token_amount: UiTokenAmount {
714 ui_amount: if (ui_token_amount.ui_amount - f64::default()).abs() > f64::EPSILON {
715 Some(ui_token_amount.ui_amount)
716 } else {
717 None
718 },
719 decimals: ui_token_amount.decimals as u8,
720 amount: ui_token_amount.amount.clone(),
721 ui_amount_string: if !ui_token_amount.ui_amount_string.is_empty() {
722 ui_token_amount.ui_amount_string
723 } else {
724 real_number_string_trimmed(
725 u64::from_str(&ui_token_amount.amount).unwrap_or_default(),
726 ui_token_amount.decimals as u8,
727 )
728 },
729 },
730 owner: value.owner,
731 program_id: value.program_id,
732 }
733 }
734}
735
736impl From<MessageAddressTableLookup> for generated::MessageAddressTableLookup {
737 fn from(lookup: MessageAddressTableLookup) -> Self {
738 Self {
739 account_key: <Pubkey as AsRef<[u8]>>::as_ref(&lookup.account_key).into(),
740 writable_indexes: lookup.writable_indexes,
741 readonly_indexes: lookup.readonly_indexes,
742 }
743 }
744}
745
746impl From<generated::MessageAddressTableLookup> for MessageAddressTableLookup {
747 fn from(value: generated::MessageAddressTableLookup) -> Self {
748 Self {
749 account_key: Pubkey::try_from(value.account_key).unwrap(),
750 writable_indexes: value.writable_indexes,
751 readonly_indexes: value.readonly_indexes,
752 }
753 }
754}
755
756impl From<TransactionReturnData> for generated::ReturnData {
757 fn from(value: TransactionReturnData) -> Self {
758 Self {
759 program_id: <Pubkey as AsRef<[u8]>>::as_ref(&value.program_id).into(),
760 data: value.data,
761 }
762 }
763}
764
765impl From<generated::ReturnData> for TransactionReturnData {
766 fn from(value: generated::ReturnData) -> Self {
767 Self {
768 program_id: Pubkey::try_from(value.program_id).unwrap(),
769 data: value.data,
770 }
771 }
772}
773
774impl From<CompiledInstruction> for generated::CompiledInstruction {
775 fn from(value: CompiledInstruction) -> Self {
776 Self {
777 program_id_index: value.program_id_index as u32,
778 accounts: value.accounts,
779 data: value.data,
780 }
781 }
782}
783
784impl From<generated::CompiledInstruction> for CompiledInstruction {
785 fn from(value: generated::CompiledInstruction) -> Self {
786 Self {
787 program_id_index: value.program_id_index as u8,
788 accounts: value.accounts,
789 data: value.data,
790 }
791 }
792}
793
794impl From<InnerInstruction> for generated::InnerInstruction {
795 fn from(value: InnerInstruction) -> Self {
796 Self {
797 program_id_index: value.instruction.program_id_index as u32,
798 accounts: value.instruction.accounts,
799 data: value.instruction.data,
800 stack_height: value.stack_height,
801 }
802 }
803}
804
805impl From<generated::InnerInstruction> for InnerInstruction {
806 fn from(value: generated::InnerInstruction) -> Self {
807 Self {
808 instruction: CompiledInstruction {
809 program_id_index: value.program_id_index as u8,
810 accounts: value.accounts,
811 data: value.data,
812 },
813 stack_height: value.stack_height,
814 }
815 }
816}
817
818impl TryFrom<tx_by_addr::TransactionError> for TransactionError {
819 type Error = &'static str;
820
821 fn try_from(transaction_error: tx_by_addr::TransactionError) -> Result<Self, Self::Error> {
822 if transaction_error.transaction_error == 8
823 && let Some(instruction_error) = transaction_error.instruction_error
824 {
825 if let Some(custom) = instruction_error.custom {
826 return Ok(TransactionError::InstructionError(
827 instruction_error.index as u8,
828 InstructionError::Custom(custom.custom),
829 ));
830 }
831
832 let ie = match instruction_error.error {
833 0 => InstructionError::GenericError,
834 1 => InstructionError::InvalidArgument,
835 2 => InstructionError::InvalidInstructionData,
836 3 => InstructionError::InvalidAccountData,
837 4 => InstructionError::AccountDataTooSmall,
838 5 => InstructionError::InsufficientFunds,
839 6 => InstructionError::IncorrectProgramId,
840 7 => InstructionError::MissingRequiredSignature,
841 8 => InstructionError::AccountAlreadyInitialized,
842 9 => InstructionError::UninitializedAccount,
843 10 => InstructionError::UnbalancedInstruction,
844 11 => InstructionError::ModifiedProgramId,
845 12 => InstructionError::ExternalAccountLamportSpend,
846 13 => InstructionError::ExternalAccountDataModified,
847 14 => InstructionError::ReadonlyLamportChange,
848 15 => InstructionError::ReadonlyDataModified,
849 16 => InstructionError::DuplicateAccountIndex,
850 17 => InstructionError::ExecutableModified,
851 18 => InstructionError::RentEpochModified,
852 #[allow(deprecated)]
853 19 => InstructionError::NotEnoughAccountKeys,
854 20 => InstructionError::AccountDataSizeChanged,
855 21 => InstructionError::AccountNotExecutable,
856 22 => InstructionError::AccountBorrowFailed,
857 23 => InstructionError::AccountBorrowOutstanding,
858 24 => InstructionError::DuplicateAccountOutOfSync,
859 26 => InstructionError::InvalidError,
860 27 => InstructionError::ExecutableDataModified,
861 28 => InstructionError::ExecutableLamportChange,
862 29 => InstructionError::ExecutableAccountNotRentExempt,
863 30 => InstructionError::UnsupportedProgramId,
864 31 => InstructionError::CallDepth,
865 32 => InstructionError::MissingAccount,
866 33 => InstructionError::ReentrancyNotAllowed,
867 34 => InstructionError::MaxSeedLengthExceeded,
868 35 => InstructionError::InvalidSeeds,
869 36 => InstructionError::InvalidRealloc,
870 37 => InstructionError::ComputationalBudgetExceeded,
871 38 => InstructionError::PrivilegeEscalation,
872 39 => InstructionError::ProgramEnvironmentSetupFailure,
873 40 => InstructionError::ProgramFailedToComplete,
874 41 => InstructionError::ProgramFailedToCompile,
875 42 => InstructionError::Immutable,
876 43 => InstructionError::IncorrectAuthority,
877 44 => InstructionError::BorshIoError,
878 45 => InstructionError::AccountNotRentExempt,
879 46 => InstructionError::InvalidAccountOwner,
880 47 => InstructionError::ArithmeticOverflow,
881 48 => InstructionError::UnsupportedSysvar,
882 49 => InstructionError::IllegalOwner,
883 50 => InstructionError::MaxAccountsDataAllocationsExceeded,
884 51 => InstructionError::MaxAccountsExceeded,
885 52 => InstructionError::MaxInstructionTraceLengthExceeded,
886 53 => InstructionError::BuiltinProgramsMustConsumeComputeUnits,
887 _ => return Err("Invalid InstructionError"),
888 };
889
890 return Ok(TransactionError::InstructionError(
891 instruction_error.index as u8,
892 ie,
893 ));
894 }
895
896 if let Some(transaction_details) = transaction_error.transaction_details {
897 match transaction_error.transaction_error {
898 30 => {
899 return Ok(TransactionError::DuplicateInstruction(
900 transaction_details.index as u8,
901 ));
902 }
903 31 => {
904 return Ok(TransactionError::InsufficientFundsForRent {
905 account_index: transaction_details.index as u8,
906 });
907 }
908
909 35 => {
910 return Ok(TransactionError::ProgramExecutionTemporarilyRestricted {
911 account_index: transaction_details.index as u8,
912 });
913 }
914 _ => {}
915 }
916 }
917
918 Ok(match transaction_error.transaction_error {
919 0 => TransactionError::AccountInUse,
920 1 => TransactionError::AccountLoadedTwice,
921 2 => TransactionError::AccountNotFound,
922 3 => TransactionError::ProgramAccountNotFound,
923 4 => TransactionError::InsufficientFundsForFee,
924 5 => TransactionError::InvalidAccountForFee,
925 6 => TransactionError::AlreadyProcessed,
926 7 => TransactionError::BlockhashNotFound,
927 9 => TransactionError::CallChainTooDeep,
928 10 => TransactionError::MissingSignatureForFee,
929 11 => TransactionError::InvalidAccountIndex,
930 12 => TransactionError::SignatureFailure,
931 13 => TransactionError::InvalidProgramForExecution,
932 14 => TransactionError::SanitizeFailure,
933 15 => TransactionError::ClusterMaintenance,
934 16 => TransactionError::AccountBorrowOutstanding,
935 17 => TransactionError::WouldExceedMaxBlockCostLimit,
936 18 => TransactionError::UnsupportedVersion,
937 19 => TransactionError::InvalidWritableAccount,
938 20 => TransactionError::WouldExceedMaxAccountCostLimit,
939 21 => TransactionError::WouldExceedAccountDataBlockLimit,
940 22 => TransactionError::TooManyAccountLocks,
941 23 => TransactionError::AddressLookupTableNotFound,
942 24 => TransactionError::InvalidAddressLookupTableOwner,
943 25 => TransactionError::InvalidAddressLookupTableData,
944 26 => TransactionError::InvalidAddressLookupTableIndex,
945 27 => TransactionError::InvalidRentPayingAccount,
946 28 => TransactionError::WouldExceedMaxVoteCostLimit,
947 29 => TransactionError::WouldExceedAccountDataTotalLimit,
948 32 => TransactionError::MaxLoadedAccountsDataSizeExceeded,
949 33 => TransactionError::InvalidLoadedAccountsDataSizeLimit,
950 34 => TransactionError::ResanitizationNeeded,
951 36 => TransactionError::UnbalancedTransaction,
952 37 => TransactionError::ProgramCacheHitMaxLimit,
953 38 => TransactionError::CommitCancelled,
954 _ => return Err("Invalid TransactionError"),
955 })
956 }
957}
958
959impl From<TransactionError> for tx_by_addr::TransactionError {
960 fn from(transaction_error: TransactionError) -> Self {
961 Self {
962 transaction_error: match transaction_error {
963 TransactionError::AccountInUse => tx_by_addr::TransactionErrorType::AccountInUse,
964 TransactionError::AccountLoadedTwice => {
965 tx_by_addr::TransactionErrorType::AccountLoadedTwice
966 }
967 TransactionError::AccountNotFound => {
968 tx_by_addr::TransactionErrorType::AccountNotFound
969 }
970 TransactionError::ProgramAccountNotFound => {
971 tx_by_addr::TransactionErrorType::ProgramAccountNotFound
972 }
973 TransactionError::InsufficientFundsForFee => {
974 tx_by_addr::TransactionErrorType::InsufficientFundsForFee
975 }
976 TransactionError::InvalidAccountForFee => {
977 tx_by_addr::TransactionErrorType::InvalidAccountForFee
978 }
979 TransactionError::AlreadyProcessed => {
980 tx_by_addr::TransactionErrorType::AlreadyProcessed
981 }
982 TransactionError::BlockhashNotFound => {
983 tx_by_addr::TransactionErrorType::BlockhashNotFound
984 }
985 TransactionError::CallChainTooDeep => {
986 tx_by_addr::TransactionErrorType::CallChainTooDeep
987 }
988 TransactionError::MissingSignatureForFee => {
989 tx_by_addr::TransactionErrorType::MissingSignatureForFee
990 }
991 TransactionError::InvalidAccountIndex => {
992 tx_by_addr::TransactionErrorType::InvalidAccountIndex
993 }
994 TransactionError::SignatureFailure => {
995 tx_by_addr::TransactionErrorType::SignatureFailure
996 }
997 TransactionError::InvalidProgramForExecution => {
998 tx_by_addr::TransactionErrorType::InvalidProgramForExecution
999 }
1000 TransactionError::SanitizeFailure => {
1001 tx_by_addr::TransactionErrorType::SanitizeFailure
1002 }
1003 TransactionError::ClusterMaintenance => {
1004 tx_by_addr::TransactionErrorType::ClusterMaintenance
1005 }
1006 TransactionError::InstructionError(_, _) => {
1007 tx_by_addr::TransactionErrorType::InstructionError
1008 }
1009 TransactionError::AccountBorrowOutstanding => {
1010 tx_by_addr::TransactionErrorType::AccountBorrowOutstandingTx
1011 }
1012 TransactionError::WouldExceedMaxBlockCostLimit => {
1013 tx_by_addr::TransactionErrorType::WouldExceedMaxBlockCostLimit
1014 }
1015 TransactionError::UnsupportedVersion => {
1016 tx_by_addr::TransactionErrorType::UnsupportedVersion
1017 }
1018 TransactionError::InvalidWritableAccount => {
1019 tx_by_addr::TransactionErrorType::InvalidWritableAccount
1020 }
1021 TransactionError::WouldExceedMaxAccountCostLimit => {
1022 tx_by_addr::TransactionErrorType::WouldExceedMaxAccountCostLimit
1023 }
1024 TransactionError::WouldExceedAccountDataBlockLimit => {
1025 tx_by_addr::TransactionErrorType::WouldExceedAccountDataBlockLimit
1026 }
1027 TransactionError::TooManyAccountLocks => {
1028 tx_by_addr::TransactionErrorType::TooManyAccountLocks
1029 }
1030 TransactionError::AddressLookupTableNotFound => {
1031 tx_by_addr::TransactionErrorType::AddressLookupTableNotFound
1032 }
1033 TransactionError::InvalidAddressLookupTableOwner => {
1034 tx_by_addr::TransactionErrorType::InvalidAddressLookupTableOwner
1035 }
1036 TransactionError::InvalidAddressLookupTableData => {
1037 tx_by_addr::TransactionErrorType::InvalidAddressLookupTableData
1038 }
1039 TransactionError::InvalidAddressLookupTableIndex => {
1040 tx_by_addr::TransactionErrorType::InvalidAddressLookupTableIndex
1041 }
1042 TransactionError::InvalidRentPayingAccount => {
1043 tx_by_addr::TransactionErrorType::InvalidRentPayingAccount
1044 }
1045 TransactionError::WouldExceedMaxVoteCostLimit => {
1046 tx_by_addr::TransactionErrorType::WouldExceedMaxVoteCostLimit
1047 }
1048 TransactionError::WouldExceedAccountDataTotalLimit => {
1049 tx_by_addr::TransactionErrorType::WouldExceedAccountDataTotalLimit
1050 }
1051 TransactionError::DuplicateInstruction(_) => {
1052 tx_by_addr::TransactionErrorType::DuplicateInstruction
1053 }
1054 TransactionError::InsufficientFundsForRent { .. } => {
1055 tx_by_addr::TransactionErrorType::InsufficientFundsForRent
1056 }
1057 TransactionError::MaxLoadedAccountsDataSizeExceeded => {
1058 tx_by_addr::TransactionErrorType::MaxLoadedAccountsDataSizeExceeded
1059 }
1060 TransactionError::InvalidLoadedAccountsDataSizeLimit => {
1061 tx_by_addr::TransactionErrorType::InvalidLoadedAccountsDataSizeLimit
1062 }
1063 TransactionError::ResanitizationNeeded => {
1064 tx_by_addr::TransactionErrorType::ResanitizationNeeded
1065 }
1066 TransactionError::ProgramExecutionTemporarilyRestricted { .. } => {
1067 tx_by_addr::TransactionErrorType::ProgramExecutionTemporarilyRestricted
1068 }
1069 TransactionError::UnbalancedTransaction => {
1070 tx_by_addr::TransactionErrorType::UnbalancedTransaction
1071 }
1072 TransactionError::ProgramCacheHitMaxLimit => {
1073 tx_by_addr::TransactionErrorType::ProgramCacheHitMaxLimit
1074 }
1075 TransactionError::CommitCancelled => {
1076 tx_by_addr::TransactionErrorType::CommitCancelled
1077 }
1078 } as i32,
1079 instruction_error: match transaction_error {
1080 TransactionError::InstructionError(index, ref instruction_error) => {
1081 Some(tx_by_addr::InstructionError {
1082 index: index as u32,
1083 error: match instruction_error {
1084 InstructionError::GenericError => {
1085 tx_by_addr::InstructionErrorType::GenericError
1086 }
1087 InstructionError::InvalidArgument => {
1088 tx_by_addr::InstructionErrorType::InvalidArgument
1089 }
1090 InstructionError::InvalidInstructionData => {
1091 tx_by_addr::InstructionErrorType::InvalidInstructionData
1092 }
1093 InstructionError::InvalidAccountData => {
1094 tx_by_addr::InstructionErrorType::InvalidAccountData
1095 }
1096 InstructionError::AccountDataTooSmall => {
1097 tx_by_addr::InstructionErrorType::AccountDataTooSmall
1098 }
1099 InstructionError::InsufficientFunds => {
1100 tx_by_addr::InstructionErrorType::InsufficientFunds
1101 }
1102 InstructionError::IncorrectProgramId => {
1103 tx_by_addr::InstructionErrorType::IncorrectProgramId
1104 }
1105 InstructionError::MissingRequiredSignature => {
1106 tx_by_addr::InstructionErrorType::MissingRequiredSignature
1107 }
1108 InstructionError::AccountAlreadyInitialized => {
1109 tx_by_addr::InstructionErrorType::AccountAlreadyInitialized
1110 }
1111 InstructionError::UninitializedAccount => {
1112 tx_by_addr::InstructionErrorType::UninitializedAccount
1113 }
1114 InstructionError::UnbalancedInstruction => {
1115 tx_by_addr::InstructionErrorType::UnbalancedInstruction
1116 }
1117 InstructionError::ModifiedProgramId => {
1118 tx_by_addr::InstructionErrorType::ModifiedProgramId
1119 }
1120 InstructionError::ExternalAccountLamportSpend => {
1121 tx_by_addr::InstructionErrorType::ExternalAccountLamportSpend
1122 }
1123 InstructionError::ExternalAccountDataModified => {
1124 tx_by_addr::InstructionErrorType::ExternalAccountDataModified
1125 }
1126 InstructionError::ReadonlyLamportChange => {
1127 tx_by_addr::InstructionErrorType::ReadonlyLamportChange
1128 }
1129 InstructionError::ReadonlyDataModified => {
1130 tx_by_addr::InstructionErrorType::ReadonlyDataModified
1131 }
1132 InstructionError::DuplicateAccountIndex => {
1133 tx_by_addr::InstructionErrorType::DuplicateAccountIndex
1134 }
1135 InstructionError::ExecutableModified => {
1136 tx_by_addr::InstructionErrorType::ExecutableModified
1137 }
1138 InstructionError::RentEpochModified => {
1139 tx_by_addr::InstructionErrorType::RentEpochModified
1140 }
1141 #[allow(deprecated)]
1142 InstructionError::NotEnoughAccountKeys => {
1143 tx_by_addr::InstructionErrorType::NotEnoughAccountKeys
1144 }
1145 InstructionError::AccountDataSizeChanged => {
1146 tx_by_addr::InstructionErrorType::AccountDataSizeChanged
1147 }
1148 InstructionError::AccountNotExecutable => {
1149 tx_by_addr::InstructionErrorType::AccountNotExecutable
1150 }
1151 InstructionError::AccountBorrowFailed => {
1152 tx_by_addr::InstructionErrorType::AccountBorrowFailed
1153 }
1154 InstructionError::AccountBorrowOutstanding => {
1155 tx_by_addr::InstructionErrorType::AccountBorrowOutstanding
1156 }
1157 InstructionError::DuplicateAccountOutOfSync => {
1158 tx_by_addr::InstructionErrorType::DuplicateAccountOutOfSync
1159 }
1160 InstructionError::Custom(_) => tx_by_addr::InstructionErrorType::Custom,
1161 InstructionError::InvalidError => {
1162 tx_by_addr::InstructionErrorType::InvalidError
1163 }
1164 InstructionError::ExecutableDataModified => {
1165 tx_by_addr::InstructionErrorType::ExecutableDataModified
1166 }
1167 InstructionError::ExecutableLamportChange => {
1168 tx_by_addr::InstructionErrorType::ExecutableLamportChange
1169 }
1170 InstructionError::ExecutableAccountNotRentExempt => {
1171 tx_by_addr::InstructionErrorType::ExecutableAccountNotRentExempt
1172 }
1173 InstructionError::UnsupportedProgramId => {
1174 tx_by_addr::InstructionErrorType::UnsupportedProgramId
1175 }
1176 InstructionError::CallDepth => {
1177 tx_by_addr::InstructionErrorType::CallDepth
1178 }
1179 InstructionError::MissingAccount => {
1180 tx_by_addr::InstructionErrorType::MissingAccount
1181 }
1182 InstructionError::ReentrancyNotAllowed => {
1183 tx_by_addr::InstructionErrorType::ReentrancyNotAllowed
1184 }
1185 InstructionError::MaxSeedLengthExceeded => {
1186 tx_by_addr::InstructionErrorType::MaxSeedLengthExceeded
1187 }
1188 InstructionError::InvalidSeeds => {
1189 tx_by_addr::InstructionErrorType::InvalidSeeds
1190 }
1191 InstructionError::InvalidRealloc => {
1192 tx_by_addr::InstructionErrorType::InvalidRealloc
1193 }
1194 InstructionError::ComputationalBudgetExceeded => {
1195 tx_by_addr::InstructionErrorType::ComputationalBudgetExceeded
1196 }
1197 InstructionError::PrivilegeEscalation => {
1198 tx_by_addr::InstructionErrorType::PrivilegeEscalation
1199 }
1200 InstructionError::ProgramEnvironmentSetupFailure => {
1201 tx_by_addr::InstructionErrorType::ProgramEnvironmentSetupFailure
1202 }
1203 InstructionError::ProgramFailedToComplete => {
1204 tx_by_addr::InstructionErrorType::ProgramFailedToComplete
1205 }
1206 InstructionError::ProgramFailedToCompile => {
1207 tx_by_addr::InstructionErrorType::ProgramFailedToCompile
1208 }
1209 InstructionError::Immutable => {
1210 tx_by_addr::InstructionErrorType::Immutable
1211 }
1212 InstructionError::IncorrectAuthority => {
1213 tx_by_addr::InstructionErrorType::IncorrectAuthority
1214 }
1215 InstructionError::BorshIoError => {
1216 tx_by_addr::InstructionErrorType::BorshIoError
1217 }
1218 InstructionError::AccountNotRentExempt => {
1219 tx_by_addr::InstructionErrorType::AccountNotRentExempt
1220 }
1221 InstructionError::InvalidAccountOwner => {
1222 tx_by_addr::InstructionErrorType::InvalidAccountOwner
1223 }
1224 InstructionError::ArithmeticOverflow => {
1225 tx_by_addr::InstructionErrorType::ArithmeticOverflow
1226 }
1227 InstructionError::UnsupportedSysvar => {
1228 tx_by_addr::InstructionErrorType::UnsupportedSysvar
1229 }
1230 InstructionError::IllegalOwner => {
1231 tx_by_addr::InstructionErrorType::IllegalOwner
1232 }
1233 InstructionError::MaxAccountsDataAllocationsExceeded => {
1234 tx_by_addr::InstructionErrorType::MaxAccountsDataAllocationsExceeded
1235 }
1236 InstructionError::MaxAccountsExceeded => {
1237 tx_by_addr::InstructionErrorType::MaxAccountsExceeded
1238 }
1239 InstructionError::MaxInstructionTraceLengthExceeded => {
1240 tx_by_addr::InstructionErrorType::MaxInstructionTraceLengthExceeded
1241 }
1242 InstructionError::BuiltinProgramsMustConsumeComputeUnits => {
1243 tx_by_addr::InstructionErrorType::BuiltinProgramsMustConsumeComputeUnits
1244 }
1245 } as i32,
1246 custom: match instruction_error {
1247 InstructionError::Custom(custom) => {
1248 Some(tx_by_addr::CustomError { custom: *custom })
1249 }
1250 _ => None,
1251 },
1252 })
1253 }
1254 _ => None,
1255 },
1256 transaction_details: match transaction_error {
1257 TransactionError::DuplicateInstruction(index) => {
1258 Some(tx_by_addr::TransactionDetails {
1259 index: index as u32,
1260 })
1261 }
1262 TransactionError::InsufficientFundsForRent { account_index } => {
1263 Some(tx_by_addr::TransactionDetails {
1264 index: account_index as u32,
1265 })
1266 }
1267 TransactionError::ProgramExecutionTemporarilyRestricted { account_index } => {
1268 Some(tx_by_addr::TransactionDetails {
1269 index: account_index as u32,
1270 })
1271 }
1272
1273 _ => None,
1274 },
1275 }
1276 }
1277}
1278
1279impl From<TransactionByAddrInfo> for tx_by_addr::TransactionByAddrInfo {
1280 fn from(by_addr: TransactionByAddrInfo) -> Self {
1281 let TransactionByAddrInfo {
1282 signature,
1283 err,
1284 index,
1285 memo,
1286 block_time,
1287 } = by_addr;
1288
1289 Self {
1290 signature: <Signature as AsRef<[u8]>>::as_ref(&signature).into(),
1291 err: err.map(|e| e.into()),
1292 index,
1293 memo: memo.map(|memo| tx_by_addr::Memo { memo }),
1294 block_time: block_time.map(|timestamp| tx_by_addr::UnixTimestamp { timestamp }),
1295 }
1296 }
1297}
1298
1299impl TryFrom<tx_by_addr::TransactionByAddrInfo> for TransactionByAddrInfo {
1300 type Error = &'static str;
1301
1302 fn try_from(
1303 transaction_by_addr: tx_by_addr::TransactionByAddrInfo,
1304 ) -> Result<Self, Self::Error> {
1305 let err = transaction_by_addr
1306 .err
1307 .map(|err| err.try_into())
1308 .transpose()?;
1309
1310 Ok(Self {
1311 signature: Signature::try_from(transaction_by_addr.signature)
1312 .map_err(|_| "Invalid Signature")?,
1313 err,
1314 index: transaction_by_addr.index,
1315 memo: transaction_by_addr
1316 .memo
1317 .map(|tx_by_addr::Memo { memo }| memo),
1318 block_time: transaction_by_addr
1319 .block_time
1320 .map(|tx_by_addr::UnixTimestamp { timestamp }| timestamp),
1321 })
1322 }
1323}
1324
1325impl TryFrom<tx_by_addr::TransactionByAddr> for Vec<TransactionByAddrInfo> {
1326 type Error = &'static str;
1327
1328 fn try_from(collection: tx_by_addr::TransactionByAddr) -> Result<Self, Self::Error> {
1329 collection
1330 .tx_by_addrs
1331 .into_iter()
1332 .map(|tx_by_addr| tx_by_addr.try_into())
1333 .collect::<Result<Vec<TransactionByAddrInfo>, Self::Error>>()
1334 }
1335}
1336
1337impl From<(usize, EntrySummary)> for entries::Entry {
1338 fn from((index, entry_summary): (usize, EntrySummary)) -> Self {
1339 entries::Entry {
1340 index: index as u32,
1341 num_hashes: entry_summary.num_hashes,
1342 hash: entry_summary.hash.as_ref().into(),
1343 num_transactions: entry_summary.num_transactions,
1344 starting_transaction_index: entry_summary.starting_transaction_index as u32,
1345 }
1346 }
1347}
1348
1349impl From<entries::Entry> for EntrySummary {
1350 fn from(entry: entries::Entry) -> Self {
1351 EntrySummary {
1352 num_hashes: entry.num_hashes,
1353 hash: <[u8; HASH_BYTES]>::try_from(entry.hash)
1354 .map(Hash::new_from_array)
1355 .unwrap(),
1356 num_transactions: entry.num_transactions,
1357 starting_transaction_index: entry.starting_transaction_index as usize,
1358 }
1359 }
1360}
1361
1362#[cfg(test)]
1363mod test {
1364 use {super::*, enum_iterator::all};
1365
1366 fn header() -> MessageHeader {
1367 MessageHeader {
1368 num_required_signatures: 1,
1369 num_readonly_signed_accounts: 0,
1370 num_readonly_unsigned_accounts: 1,
1371 }
1372 }
1373
1374 fn account_keys() -> Vec<Pubkey> {
1375 vec![
1376 Pubkey::new_unique(),
1377 Pubkey::new_unique(),
1378 Pubkey::new_unique(),
1379 ]
1380 }
1381
1382 fn instructions() -> Vec<CompiledInstruction> {
1383 vec![CompiledInstruction {
1384 program_id_index: 2,
1385 accounts: vec![0, 1],
1386 data: vec![1, 2, 3, 4],
1387 }]
1388 }
1389
1390 fn round_trip(message: VersionedMessage) -> VersionedMessage {
1391 VersionedMessage::from(generated::Message::from(message))
1392 }
1393
1394 #[test]
1395 fn test_reward_type_encode() {
1396 let mut reward = Reward {
1397 pubkey: "invalid".to_string(),
1398 lamports: 123,
1399 post_balance: 321,
1400 reward_type: None,
1401 commission: None,
1402 commission_bps: None,
1403 };
1404 let gen_reward: generated::Reward = reward.clone().into();
1405 assert_eq!(reward, gen_reward.into());
1406
1407 reward.reward_type = Some(RewardType::Fee);
1408 let gen_reward: generated::Reward = reward.clone().into();
1409 assert_eq!(reward, gen_reward.into());
1410
1411 reward.reward_type = Some(RewardType::Rent);
1412 let gen_reward: generated::Reward = reward.clone().into();
1413 assert_eq!(reward, gen_reward.into());
1414
1415 reward.reward_type = Some(RewardType::Voting);
1416 let gen_reward: generated::Reward = reward.clone().into();
1417 assert_eq!(reward, gen_reward.into());
1418
1419 reward.reward_type = Some(RewardType::Staking);
1420 let gen_reward: generated::Reward = reward.clone().into();
1421 assert_eq!(reward, gen_reward.into());
1422
1423 reward.reward_type = Some(RewardType::DeactivatedStake);
1424 let gen_reward: generated::Reward = reward.clone().into();
1425 assert_eq!(reward, gen_reward.into());
1426 }
1427
1428 #[test]
1429 fn test_transaction_by_addr_encode() {
1430 let info = TransactionByAddrInfo {
1431 signature: bs58::decode("Nfo6rgemG1KLbk1xuNwfrQTsdxaGfLuWURHNRy9LYnDrubG7LFQZaA5obPNas9LQ6DdorJqxh2LxA3PsnWdkSrL")
1432 .into_vec()
1433 .map(Signature::try_from)
1434 .unwrap()
1435 .unwrap(),
1436 err: None,
1437 index: 5,
1438 memo: Some("string".to_string()),
1439 block_time: Some(1610674861)
1440 };
1441
1442 let tx_by_addr_transaction_info: tx_by_addr::TransactionByAddrInfo = info.clone().into();
1443 assert_eq!(info, tx_by_addr_transaction_info.try_into().unwrap());
1444 }
1445
1446 #[test]
1447 fn test_transaction_error_encode() {
1448 let transaction_error = TransactionError::AccountBorrowOutstanding;
1449 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1450 transaction_error.clone().into();
1451 assert_eq!(
1452 transaction_error,
1453 tx_by_addr_transaction_error.try_into().unwrap()
1454 );
1455
1456 let transaction_error = TransactionError::AccountInUse;
1457 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1458 transaction_error.clone().into();
1459 assert_eq!(
1460 transaction_error,
1461 tx_by_addr_transaction_error.try_into().unwrap()
1462 );
1463
1464 let transaction_error = TransactionError::AccountLoadedTwice;
1465 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1466 transaction_error.clone().into();
1467 assert_eq!(
1468 transaction_error,
1469 tx_by_addr_transaction_error.try_into().unwrap()
1470 );
1471
1472 let transaction_error = TransactionError::AccountNotFound;
1473 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1474 transaction_error.clone().into();
1475 assert_eq!(
1476 transaction_error,
1477 tx_by_addr_transaction_error.try_into().unwrap()
1478 );
1479
1480 let transaction_error = TransactionError::AlreadyProcessed;
1481 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1482 transaction_error.clone().into();
1483 assert_eq!(
1484 transaction_error,
1485 tx_by_addr_transaction_error.try_into().unwrap()
1486 );
1487
1488 let transaction_error = TransactionError::BlockhashNotFound;
1489 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1490 transaction_error.clone().into();
1491 assert_eq!(
1492 transaction_error,
1493 tx_by_addr_transaction_error.try_into().unwrap()
1494 );
1495
1496 let transaction_error = TransactionError::CallChainTooDeep;
1497 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1498 transaction_error.clone().into();
1499 assert_eq!(
1500 transaction_error,
1501 tx_by_addr_transaction_error.try_into().unwrap()
1502 );
1503
1504 let transaction_error = TransactionError::ClusterMaintenance;
1505 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1506 transaction_error.clone().into();
1507 assert_eq!(
1508 transaction_error,
1509 tx_by_addr_transaction_error.try_into().unwrap()
1510 );
1511
1512 let transaction_error = TransactionError::InsufficientFundsForFee;
1513 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1514 transaction_error.clone().into();
1515 assert_eq!(
1516 transaction_error,
1517 tx_by_addr_transaction_error.try_into().unwrap()
1518 );
1519
1520 let transaction_error = TransactionError::InvalidAccountForFee;
1521 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1522 transaction_error.clone().into();
1523 assert_eq!(
1524 transaction_error,
1525 tx_by_addr_transaction_error.try_into().unwrap()
1526 );
1527
1528 let transaction_error = TransactionError::InvalidAccountIndex;
1529 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1530 transaction_error.clone().into();
1531 assert_eq!(
1532 transaction_error,
1533 tx_by_addr_transaction_error.try_into().unwrap()
1534 );
1535
1536 let transaction_error = TransactionError::InvalidProgramForExecution;
1537 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1538 transaction_error.clone().into();
1539 assert_eq!(
1540 transaction_error,
1541 tx_by_addr_transaction_error.try_into().unwrap()
1542 );
1543
1544 let transaction_error = TransactionError::MissingSignatureForFee;
1545 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1546 transaction_error.clone().into();
1547 assert_eq!(
1548 transaction_error,
1549 tx_by_addr_transaction_error.try_into().unwrap()
1550 );
1551
1552 let transaction_error = TransactionError::ProgramAccountNotFound;
1553 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1554 transaction_error.clone().into();
1555 assert_eq!(
1556 transaction_error,
1557 tx_by_addr_transaction_error.try_into().unwrap()
1558 );
1559
1560 let transaction_error = TransactionError::SanitizeFailure;
1561 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1562 transaction_error.clone().into();
1563 assert_eq!(
1564 transaction_error,
1565 tx_by_addr_transaction_error.try_into().unwrap()
1566 );
1567
1568 let transaction_error = TransactionError::SignatureFailure;
1569 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1570 transaction_error.clone().into();
1571 assert_eq!(
1572 transaction_error,
1573 tx_by_addr_transaction_error.try_into().unwrap()
1574 );
1575
1576 let transaction_error = TransactionError::WouldExceedMaxBlockCostLimit;
1577 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1578 transaction_error.clone().into();
1579 assert_eq!(
1580 transaction_error,
1581 tx_by_addr_transaction_error.try_into().unwrap()
1582 );
1583
1584 let transaction_error = TransactionError::WouldExceedMaxVoteCostLimit;
1585 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1586 transaction_error.clone().into();
1587 assert_eq!(
1588 transaction_error,
1589 tx_by_addr_transaction_error.try_into().unwrap()
1590 );
1591
1592 let transaction_error = TransactionError::WouldExceedMaxAccountCostLimit;
1593 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1594 transaction_error.clone().into();
1595 assert_eq!(
1596 transaction_error,
1597 tx_by_addr_transaction_error.try_into().unwrap()
1598 );
1599
1600 let transaction_error = TransactionError::UnsupportedVersion;
1601 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1602 transaction_error.clone().into();
1603 assert_eq!(
1604 transaction_error,
1605 tx_by_addr_transaction_error.try_into().unwrap()
1606 );
1607
1608 let transaction_error =
1609 TransactionError::InstructionError(10, InstructionError::AccountAlreadyInitialized);
1610 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1611 transaction_error.clone().into();
1612 assert_eq!(
1613 transaction_error,
1614 tx_by_addr_transaction_error.try_into().unwrap()
1615 );
1616
1617 let transaction_error =
1618 TransactionError::InstructionError(10, InstructionError::AccountBorrowFailed);
1619 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1620 transaction_error.clone().into();
1621 assert_eq!(
1622 transaction_error,
1623 tx_by_addr_transaction_error.try_into().unwrap()
1624 );
1625
1626 let transaction_error =
1627 TransactionError::InstructionError(10, InstructionError::AccountBorrowOutstanding);
1628 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1629 transaction_error.clone().into();
1630 assert_eq!(
1631 transaction_error,
1632 tx_by_addr_transaction_error.try_into().unwrap()
1633 );
1634
1635 let transaction_error =
1636 TransactionError::InstructionError(10, InstructionError::AccountDataSizeChanged);
1637 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1638 transaction_error.clone().into();
1639 assert_eq!(
1640 transaction_error,
1641 tx_by_addr_transaction_error.try_into().unwrap()
1642 );
1643
1644 let transaction_error =
1645 TransactionError::InstructionError(10, InstructionError::AccountDataTooSmall);
1646 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1647 transaction_error.clone().into();
1648 assert_eq!(
1649 transaction_error,
1650 tx_by_addr_transaction_error.try_into().unwrap()
1651 );
1652
1653 let transaction_error =
1654 TransactionError::InstructionError(10, InstructionError::AccountNotExecutable);
1655 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1656 transaction_error.clone().into();
1657 assert_eq!(
1658 transaction_error,
1659 tx_by_addr_transaction_error.try_into().unwrap()
1660 );
1661
1662 let transaction_error = TransactionError::InstructionError(10, InstructionError::CallDepth);
1663 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1664 transaction_error.clone().into();
1665 assert_eq!(
1666 transaction_error,
1667 tx_by_addr_transaction_error.try_into().unwrap()
1668 );
1669
1670 let transaction_error =
1671 TransactionError::InstructionError(10, InstructionError::ComputationalBudgetExceeded);
1672 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1673 transaction_error.clone().into();
1674 assert_eq!(
1675 transaction_error,
1676 tx_by_addr_transaction_error.try_into().unwrap()
1677 );
1678
1679 let transaction_error =
1680 TransactionError::InstructionError(10, InstructionError::DuplicateAccountIndex);
1681 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1682 transaction_error.clone().into();
1683 assert_eq!(
1684 transaction_error,
1685 tx_by_addr_transaction_error.try_into().unwrap()
1686 );
1687
1688 let transaction_error =
1689 TransactionError::InstructionError(10, InstructionError::DuplicateAccountOutOfSync);
1690 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1691 transaction_error.clone().into();
1692 assert_eq!(
1693 transaction_error,
1694 tx_by_addr_transaction_error.try_into().unwrap()
1695 );
1696
1697 let transaction_error = TransactionError::InstructionError(
1698 10,
1699 InstructionError::ExecutableAccountNotRentExempt,
1700 );
1701 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1702 transaction_error.clone().into();
1703 assert_eq!(
1704 transaction_error,
1705 tx_by_addr_transaction_error.try_into().unwrap()
1706 );
1707
1708 let transaction_error =
1709 TransactionError::InstructionError(10, InstructionError::ExecutableDataModified);
1710 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1711 transaction_error.clone().into();
1712 assert_eq!(
1713 transaction_error,
1714 tx_by_addr_transaction_error.try_into().unwrap()
1715 );
1716
1717 let transaction_error =
1718 TransactionError::InstructionError(10, InstructionError::ExecutableLamportChange);
1719 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1720 transaction_error.clone().into();
1721 assert_eq!(
1722 transaction_error,
1723 tx_by_addr_transaction_error.try_into().unwrap()
1724 );
1725
1726 let transaction_error =
1727 TransactionError::InstructionError(10, InstructionError::ExecutableModified);
1728 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1729 transaction_error.clone().into();
1730 assert_eq!(
1731 transaction_error,
1732 tx_by_addr_transaction_error.try_into().unwrap()
1733 );
1734
1735 let transaction_error =
1736 TransactionError::InstructionError(10, InstructionError::ExternalAccountDataModified);
1737 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1738 transaction_error.clone().into();
1739 assert_eq!(
1740 transaction_error,
1741 tx_by_addr_transaction_error.try_into().unwrap()
1742 );
1743
1744 let transaction_error =
1745 TransactionError::InstructionError(10, InstructionError::ExternalAccountLamportSpend);
1746 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1747 transaction_error.clone().into();
1748 assert_eq!(
1749 transaction_error,
1750 tx_by_addr_transaction_error.try_into().unwrap()
1751 );
1752
1753 let transaction_error =
1754 TransactionError::InstructionError(10, InstructionError::GenericError);
1755 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1756 transaction_error.clone().into();
1757 assert_eq!(
1758 transaction_error,
1759 tx_by_addr_transaction_error.try_into().unwrap()
1760 );
1761
1762 let transaction_error = TransactionError::InstructionError(10, InstructionError::Immutable);
1763 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1764 transaction_error.clone().into();
1765 assert_eq!(
1766 transaction_error,
1767 tx_by_addr_transaction_error.try_into().unwrap()
1768 );
1769
1770 let transaction_error =
1771 TransactionError::InstructionError(10, InstructionError::IncorrectAuthority);
1772 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1773 transaction_error.clone().into();
1774 assert_eq!(
1775 transaction_error,
1776 tx_by_addr_transaction_error.try_into().unwrap()
1777 );
1778
1779 let transaction_error =
1780 TransactionError::InstructionError(10, InstructionError::IncorrectProgramId);
1781 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1782 transaction_error.clone().into();
1783 assert_eq!(
1784 transaction_error,
1785 tx_by_addr_transaction_error.try_into().unwrap()
1786 );
1787
1788 let transaction_error =
1789 TransactionError::InstructionError(10, InstructionError::InsufficientFunds);
1790 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1791 transaction_error.clone().into();
1792 assert_eq!(
1793 transaction_error,
1794 tx_by_addr_transaction_error.try_into().unwrap()
1795 );
1796
1797 let transaction_error =
1798 TransactionError::InstructionError(10, InstructionError::InvalidAccountData);
1799 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1800 transaction_error.clone().into();
1801 assert_eq!(
1802 transaction_error,
1803 tx_by_addr_transaction_error.try_into().unwrap()
1804 );
1805
1806 let transaction_error =
1807 TransactionError::InstructionError(10, InstructionError::InvalidArgument);
1808 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1809 transaction_error.clone().into();
1810 assert_eq!(
1811 transaction_error,
1812 tx_by_addr_transaction_error.try_into().unwrap()
1813 );
1814
1815 let transaction_error =
1816 TransactionError::InstructionError(10, InstructionError::InvalidError);
1817 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1818 transaction_error.clone().into();
1819 assert_eq!(
1820 transaction_error,
1821 tx_by_addr_transaction_error.try_into().unwrap()
1822 );
1823
1824 let transaction_error =
1825 TransactionError::InstructionError(10, InstructionError::InvalidInstructionData);
1826 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1827 transaction_error.clone().into();
1828 assert_eq!(
1829 transaction_error,
1830 tx_by_addr_transaction_error.try_into().unwrap()
1831 );
1832
1833 let transaction_error =
1834 TransactionError::InstructionError(10, InstructionError::InvalidRealloc);
1835 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1836 transaction_error.clone().into();
1837 assert_eq!(
1838 transaction_error,
1839 tx_by_addr_transaction_error.try_into().unwrap()
1840 );
1841
1842 let transaction_error =
1843 TransactionError::InstructionError(10, InstructionError::InvalidSeeds);
1844 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1845 transaction_error.clone().into();
1846 assert_eq!(
1847 transaction_error,
1848 tx_by_addr_transaction_error.try_into().unwrap()
1849 );
1850
1851 let transaction_error =
1852 TransactionError::InstructionError(10, InstructionError::MaxSeedLengthExceeded);
1853 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1854 transaction_error.clone().into();
1855 assert_eq!(
1856 transaction_error,
1857 tx_by_addr_transaction_error.try_into().unwrap()
1858 );
1859
1860 let transaction_error =
1861 TransactionError::InstructionError(10, InstructionError::MissingAccount);
1862 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1863 transaction_error.clone().into();
1864 assert_eq!(
1865 transaction_error,
1866 tx_by_addr_transaction_error.try_into().unwrap()
1867 );
1868
1869 let transaction_error =
1870 TransactionError::InstructionError(10, InstructionError::MissingRequiredSignature);
1871 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1872 transaction_error.clone().into();
1873 assert_eq!(
1874 transaction_error,
1875 tx_by_addr_transaction_error.try_into().unwrap()
1876 );
1877
1878 let transaction_error =
1879 TransactionError::InstructionError(10, InstructionError::ModifiedProgramId);
1880 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1881 transaction_error.clone().into();
1882 assert_eq!(
1883 transaction_error,
1884 tx_by_addr_transaction_error.try_into().unwrap()
1885 );
1886
1887 #[allow(deprecated)]
1888 let transaction_error =
1889 TransactionError::InstructionError(10, InstructionError::NotEnoughAccountKeys);
1890 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1891 transaction_error.clone().into();
1892 assert_eq!(
1893 transaction_error,
1894 tx_by_addr_transaction_error.try_into().unwrap()
1895 );
1896
1897 let transaction_error =
1898 TransactionError::InstructionError(10, InstructionError::PrivilegeEscalation);
1899 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1900 transaction_error.clone().into();
1901 assert_eq!(
1902 transaction_error,
1903 tx_by_addr_transaction_error.try_into().unwrap()
1904 );
1905
1906 let transaction_error = TransactionError::InstructionError(
1907 10,
1908 InstructionError::ProgramEnvironmentSetupFailure,
1909 );
1910 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1911 transaction_error.clone().into();
1912 assert_eq!(
1913 transaction_error,
1914 tx_by_addr_transaction_error.try_into().unwrap()
1915 );
1916
1917 let transaction_error =
1918 TransactionError::InstructionError(10, InstructionError::ProgramFailedToCompile);
1919 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1920 transaction_error.clone().into();
1921 assert_eq!(
1922 transaction_error,
1923 tx_by_addr_transaction_error.try_into().unwrap()
1924 );
1925
1926 let transaction_error =
1927 TransactionError::InstructionError(10, InstructionError::ProgramFailedToComplete);
1928 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1929 transaction_error.clone().into();
1930 assert_eq!(
1931 transaction_error,
1932 tx_by_addr_transaction_error.try_into().unwrap()
1933 );
1934
1935 let transaction_error =
1936 TransactionError::InstructionError(10, InstructionError::ReadonlyDataModified);
1937 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1938 transaction_error.clone().into();
1939 assert_eq!(
1940 transaction_error,
1941 tx_by_addr_transaction_error.try_into().unwrap()
1942 );
1943
1944 let transaction_error =
1945 TransactionError::InstructionError(10, InstructionError::ReadonlyLamportChange);
1946 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1947 transaction_error.clone().into();
1948 assert_eq!(
1949 transaction_error,
1950 tx_by_addr_transaction_error.try_into().unwrap()
1951 );
1952
1953 let transaction_error =
1954 TransactionError::InstructionError(10, InstructionError::ReentrancyNotAllowed);
1955 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1956 transaction_error.clone().into();
1957 assert_eq!(
1958 transaction_error,
1959 tx_by_addr_transaction_error.try_into().unwrap()
1960 );
1961
1962 let transaction_error =
1963 TransactionError::InstructionError(10, InstructionError::RentEpochModified);
1964 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1965 transaction_error.clone().into();
1966 assert_eq!(
1967 transaction_error,
1968 tx_by_addr_transaction_error.try_into().unwrap()
1969 );
1970
1971 let transaction_error =
1972 TransactionError::InstructionError(10, InstructionError::UnbalancedInstruction);
1973 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1974 transaction_error.clone().into();
1975 assert_eq!(
1976 transaction_error,
1977 tx_by_addr_transaction_error.try_into().unwrap()
1978 );
1979
1980 let transaction_error =
1981 TransactionError::InstructionError(10, InstructionError::UninitializedAccount);
1982 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1983 transaction_error.clone().into();
1984 assert_eq!(
1985 transaction_error,
1986 tx_by_addr_transaction_error.try_into().unwrap()
1987 );
1988
1989 let transaction_error =
1990 TransactionError::InstructionError(10, InstructionError::UnsupportedProgramId);
1991 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
1992 transaction_error.clone().into();
1993 assert_eq!(
1994 transaction_error,
1995 tx_by_addr_transaction_error.try_into().unwrap()
1996 );
1997
1998 let transaction_error =
1999 TransactionError::InstructionError(10, InstructionError::Custom(10));
2000 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
2001 transaction_error.clone().into();
2002 assert_eq!(
2003 transaction_error,
2004 tx_by_addr_transaction_error.try_into().unwrap()
2005 );
2006
2007 let transaction_error = TransactionError::DuplicateInstruction(10);
2008 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
2009 transaction_error.clone().into();
2010 assert_eq!(
2011 transaction_error,
2012 tx_by_addr_transaction_error.try_into().unwrap()
2013 );
2014
2015 let transaction_error = TransactionError::InsufficientFundsForRent { account_index: 10 };
2016 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
2017 transaction_error.clone().into();
2018 assert_eq!(
2019 transaction_error,
2020 tx_by_addr_transaction_error.try_into().unwrap()
2021 );
2022
2023 let transaction_error = TransactionError::UnbalancedTransaction;
2024 let tx_by_addr_transaction_error: tx_by_addr::TransactionError =
2025 transaction_error.clone().into();
2026 assert_eq!(
2027 transaction_error,
2028 tx_by_addr_transaction_error.try_into().unwrap()
2029 );
2030 }
2031
2032 #[test]
2033 fn test_error_enums() {
2034 let ix_index = 1;
2035 let custom_error = 42;
2036 for error in all::<tx_by_addr::TransactionErrorType>() {
2037 match error {
2038 tx_by_addr::TransactionErrorType::DuplicateInstruction
2039 | tx_by_addr::TransactionErrorType::InsufficientFundsForRent
2040 | tx_by_addr::TransactionErrorType::ProgramExecutionTemporarilyRestricted => {
2041 let tx_by_addr_error = tx_by_addr::TransactionError {
2042 transaction_error: error as i32,
2043 instruction_error: None,
2044 transaction_details: Some(tx_by_addr::TransactionDetails {
2045 index: ix_index,
2046 }),
2047 };
2048 let transaction_error: TransactionError = tx_by_addr_error
2049 .try_into()
2050 .unwrap_or_else(|_| panic!("{error:?} conversion implemented?"));
2051 assert_eq!(tx_by_addr_error, transaction_error.into());
2052 }
2053 tx_by_addr::TransactionErrorType::InstructionError => {
2054 for ix_error in all::<tx_by_addr::InstructionErrorType>() {
2055 if ix_error != tx_by_addr::InstructionErrorType::Custom {
2056 let tx_by_addr_error = tx_by_addr::TransactionError {
2057 transaction_error: error as i32,
2058 instruction_error: Some(tx_by_addr::InstructionError {
2059 index: ix_index,
2060 error: ix_error as i32,
2061 custom: None,
2062 }),
2063 transaction_details: None,
2064 };
2065 let transaction_error: TransactionError = tx_by_addr_error
2066 .try_into()
2067 .unwrap_or_else(|_| panic!("{ix_error:?} conversion implemented?"));
2068 assert_eq!(tx_by_addr_error, transaction_error.into());
2069 } else {
2070 let tx_by_addr_error = tx_by_addr::TransactionError {
2071 transaction_error: error as i32,
2072 instruction_error: Some(tx_by_addr::InstructionError {
2073 index: ix_index,
2074 error: ix_error as i32,
2075 custom: Some(tx_by_addr::CustomError {
2076 custom: custom_error,
2077 }),
2078 }),
2079 transaction_details: None,
2080 };
2081 let transaction_error: TransactionError =
2082 tx_by_addr_error.try_into().unwrap();
2083 assert_eq!(tx_by_addr_error, transaction_error.into());
2084 }
2085 }
2086 }
2087 _ => {
2088 let tx_by_addr_error = tx_by_addr::TransactionError {
2089 transaction_error: error as i32,
2090 instruction_error: None,
2091 transaction_details: None,
2092 };
2093 let transaction_error: TransactionError = tx_by_addr_error
2094 .try_into()
2095 .unwrap_or_else(|_| panic!("{error:?} conversion implemented?"));
2096 assert_eq!(tx_by_addr_error, transaction_error.into());
2097 }
2098 }
2099 }
2100 }
2101
2102 #[test]
2103 fn legacy_message_round_trips() {
2104 let message = VersionedMessage::Legacy(LegacyMessage {
2105 header: header(),
2106 account_keys: account_keys(),
2107 recent_blockhash: Hash::new_unique(),
2108 instructions: instructions(),
2109 });
2110 assert_eq!(round_trip(message.clone()), message);
2111 }
2112
2113 #[test]
2114 fn v0_message_round_trips() {
2115 let message = VersionedMessage::V0(v0::Message {
2116 header: header(),
2117 account_keys: account_keys(),
2118 recent_blockhash: Hash::new_unique(),
2119 instructions: instructions(),
2120 address_table_lookups: vec![MessageAddressTableLookup {
2121 account_key: Pubkey::new_unique(),
2122 writable_indexes: vec![1, 2],
2123 readonly_indexes: vec![3],
2124 }],
2125 });
2126 assert_eq!(round_trip(message.clone()), message);
2127 }
2128
2129 #[test]
2133 fn v1_message_round_trips() {
2134 let message = VersionedMessage::V1(v1::Message {
2135 header: header(),
2136 config: v1::TransactionConfig::empty()
2137 .with_priority_fee(5_000)
2138 .with_compute_unit_limit(30_000)
2139 .with_loaded_accounts_data_size_limit(200_000)
2140 .with_heap_size(65_536),
2141 lifetime_specifier: Hash::new_unique(),
2142 account_keys: account_keys(),
2143 instructions: instructions(),
2144 });
2145 assert_eq!(round_trip(message.clone()), message);
2146 }
2147
2148 #[test]
2151 fn v1_message_with_empty_config_round_trips() {
2152 let message = VersionedMessage::V1(v1::Message {
2153 header: header(),
2154 config: v1::TransactionConfig::empty(),
2155 lifetime_specifier: Hash::new_unique(),
2156 account_keys: account_keys(),
2157 instructions: instructions(),
2158 });
2159 assert_eq!(round_trip(message.clone()), message);
2160 }
2161}