Skip to content

Commit

Permalink
refactor: transfer parser fn from nft_ingester associated with the sw…
Browse files Browse the repository at this point in the history
…ap to solana structs for program_transform to preserve usage of references. Using impl required copies.
  • Loading branch information
kespinola committed Feb 27, 2024
1 parent 4e8c005 commit fece58c
Showing 1 changed file with 89 additions and 126 deletions.
215 changes: 89 additions & 126 deletions plerkle_serialization/src/deserializer/solana.rs
Original file line number Diff line number Diff line change
@@ -1,150 +1,113 @@
use super::{
OptionalCompiledInnerInstructionsVector, OptionalCompiledInstructionVector, OptionalPubkey,
OptionalPubkeyVector, OptionalStr, OptionalU8Vector,
};
use crate::Pubkey as FBPubkey;
use solana_sdk::{
instruction::CompiledInstruction,
pubkey::Pubkey,
signature::{ParseSignatureError, Signature},
use crate::{
CompiledInnerInstructions as FBCompiledInnerInstructions,
CompiledInstruction as FBCompiledInstruction, Pubkey as FBPubkey,
};
use flatbuffers::{ForwardsUOffset, Vector};
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey, signature::Signature};
use solana_transaction_status::{InnerInstruction, InnerInstructions};

#[derive(Debug, thiserror::Error)]
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum SolanaDeserializerError {
#[error("solana pubkey deserialization error")]
Pubkey,
#[error("solana signature deserialization error")]
Signature,
#[error("expected data not found in FlatBuffer")]
#[error("Deserialization error")]
DeserializationError,
#[error("Not found")]
NotFound,
#[error("Invalid FlatBuffer key")]
InvalidFlatBufferKey,
}

impl<'a> TryFrom<OptionalPubkey<'a>> for Pubkey {
type Error = SolanaDeserializerError;
pub type SolanaDeserializeResult<T> = Result<T, SolanaDeserializerError>;

fn try_from(value: OptionalPubkey<'a>) -> Result<Self, Self::Error> {
value
pub fn parse_pubkey(pubkey: Option<&FBPubkey>) -> SolanaDeserializeResult<Pubkey> {
Pubkey::try_from(
pubkey
.ok_or(SolanaDeserializerError::NotFound)?
.0
.ok_or(SolanaDeserializerError::NotFound)
.and_then(|data| Pubkey::try_from(data))
}
}

impl TryFrom<&FBPubkey> for Pubkey {
type Error = SolanaDeserializerError;

fn try_from(value: &FBPubkey) -> Result<Self, Self::Error> {
(value.0)
.try_into()
.map_err(|_| SolanaDeserializerError::Pubkey)
}
.as_slice(),
)
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)
}

impl TryFrom<FBPubkey> for Pubkey {
type Error = SolanaDeserializerError;

fn try_from(value: FBPubkey) -> Result<Self, Self::Error> {
Pubkey::try_from(value.0).map_err(|_| SolanaDeserializerError::Pubkey)
}
pub fn parse_slice(data: Option<Vector<'_, u8>>) -> SolanaDeserializeResult<&[u8]> {
data.map(|data| data.bytes())
.ok_or(SolanaDeserializerError::NotFound)
}

impl<'a> TryFrom<OptionalU8Vector<'a>> for &'a [u8] {
type Error = SolanaDeserializerError;

fn try_from(value: OptionalU8Vector<'a>) -> Result<Self, Self::Error> {
value
.0
.map(|data| data.bytes())
.ok_or(SolanaDeserializerError::NotFound)
}
pub fn parse_signature(data: Option<&str>) -> SolanaDeserializeResult<Signature> {
data.ok_or(SolanaDeserializerError::NotFound)?
.parse()
.map_err(|_error| SolanaDeserializerError::DeserializationError)
}

impl<'a> TryFrom<OptionalStr<'a>> for Signature {
type Error = SolanaDeserializerError;

fn try_from(value: OptionalStr<'a>) -> Result<Self, Self::Error> {
value
.0
.ok_or(ParseSignatureError::Invalid)
.and_then(|data| data.parse())
.map_err(|_| SolanaDeserializerError::Signature)
}
pub fn parse_account_keys(
keys: Option<Vector<'_, FBPubkey>>,
) -> SolanaDeserializeResult<Vec<Pubkey>> {
keys.ok_or(SolanaDeserializerError::NotFound)?
.iter()
.map(|key| {
Pubkey::try_from(key.0.as_slice())
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)
})
.collect::<SolanaDeserializeResult<Vec<Pubkey>>>()
}

impl<'a> TryFrom<OptionalPubkeyVector<'a>> for Vec<Pubkey> {
type Error = SolanaDeserializerError;

fn try_from(value: OptionalPubkeyVector<'a>) -> Result<Self, Self::Error> {
value
.0
.ok_or(SolanaDeserializerError::Pubkey)?
.iter()
.map(|key| Pubkey::try_from(key))
.collect::<Result<Self, Self::Error>>()
pub fn parse_message_instructions(
vec_cix: Option<Vector<'_, ForwardsUOffset<FBCompiledInstruction>>>,
) -> SolanaDeserializeResult<Vec<CompiledInstruction>> {
let mut message_instructions = vec![];
for cix in vec_cix.ok_or(SolanaDeserializerError::NotFound)? {
message_instructions.push(CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
})
}
}

impl TryFrom<OptionalCompiledInstructionVector<'_>> for Vec<CompiledInstruction> {
type Error = SolanaDeserializerError;

fn try_from(value: OptionalCompiledInstructionVector<'_>) -> Result<Self, Self::Error> {
let mut message_instructions = vec![];
for cix in value.0.ok_or(SolanaDeserializerError::NotFound)? {
message_instructions.push(CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
})
}
Ok(message_instructions)
}
Ok(message_instructions)
}

impl TryFrom<OptionalCompiledInnerInstructionsVector<'_>> for Vec<InnerInstructions> {
type Error = SolanaDeserializerError;

fn try_from(value: OptionalCompiledInnerInstructionsVector<'_>) -> Result<Self, Self::Error> {
let mut meta_inner_instructions = vec![];
for ixs in value.0.ok_or(SolanaDeserializerError::NotFound)? {
let mut instructions = vec![];
for ix in ixs
.instructions()
.ok_or(SolanaDeserializerError::NotFound)?
{
let cix = ix
.compiled_instruction()
.ok_or(SolanaDeserializerError::NotFound)?;
instructions.push(InnerInstruction {
instruction: CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(ix.stack_height() as u32),
});
}
meta_inner_instructions.push(InnerInstructions {
index: ixs.index(),
instructions,
})
pub fn parse_meta_inner_instructions(
vec_ixs: Option<Vector<'_, ForwardsUOffset<FBCompiledInnerInstructions>>>,
) -> SolanaDeserializeResult<Vec<InnerInstructions>> {
let mut meta_inner_instructions = vec![];
for ixs in vec_ixs.ok_or(SolanaDeserializerError::NotFound)? {
let mut instructions = vec![];
for ix in ixs
.instructions()
.ok_or(SolanaDeserializerError::NotFound)?
{
let cix = ix
.compiled_instruction()
.ok_or(SolanaDeserializerError::NotFound)?;
instructions.push(InnerInstruction {
instruction: CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(ix.stack_height() as u32),
});
}
Ok(meta_inner_instructions)
meta_inner_instructions.push(InnerInstructions {
index: ixs.index(),
instructions,
})
}
Ok(meta_inner_instructions)
}

0 comments on commit fece58c

Please sign in to comment.