diff --git a/Cargo.lock b/Cargo.lock index 680c45f..297cc75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1222,14 +1222,37 @@ dependencies = [ "zeroize", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.8", + "darling_macro 0.20.8", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -1246,13 +1269,24 @@ dependencies = [ "syn 2.0.59", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core", + "darling_core 0.20.8", "quote", "syn 2.0.59", ] @@ -1997,6 +2031,7 @@ dependencies = [ "mockito", "reqwest 0.12.3", "serde", + "serde-enum-str", "serde_json", "solana-client", "solana-core", @@ -4354,6 +4389,36 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-attributes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eb8ec7724e4e524b2492b510e66957fe1a2c76c26a6975ec80823f2439da685" +dependencies = [ + "darling_core 0.14.4", + "serde-rename-rule", + "syn 1.0.109", +] + +[[package]] +name = "serde-enum-str" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26416dc95fcd46b0e4b12a3758043a229a6914050aaec2e8191949753ed4e9aa" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "serde-attributes", + "syn 1.0.109", +] + +[[package]] +name = "serde-rename-rule" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794e44574226fc701e3be5c651feb7939038fc67fb73f6f4dd5c4ba90fd3be70" + [[package]] name = "serde_bytes" version = "0.11.14" @@ -4413,7 +4478,7 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" dependencies = [ - "darling", + "darling 0.20.8", "proc-macro2", "quote", "syn 2.0.59", diff --git a/Cargo.toml b/Cargo.toml index f5756be..4d2a00b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ chrono = { version = "0.4.11", features = ["serde"] } solana-client = "1.18.12" solana-core = "1.18.12" solana-program = "1.18.12" +serde-enum-str = "0.4.0" [dev-dependencies] mockito = "1.4.0" diff --git a/src/types/enhanced_transaction_types.rs b/src/types/enhanced_transaction_types.rs new file mode 100644 index 0000000..c3d0047 --- /dev/null +++ b/src/types/enhanced_transaction_types.rs @@ -0,0 +1,206 @@ +use serde::{Deserialize, Serialize}; +use serde_json::{Number, Value}; + +use super::*; +use crate::utils::deserialize_str_to_number; + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct EnhancedTransaction { + pub account_data: Vec, + pub description: String, + #[serde(rename = "type")] + pub transaction_type: TransactionType, + pub source: Source, + pub fee: i32, + pub fee_payer: String, + pub signature: String, + pub slot: i32, + pub native_transfers: Option>, + pub token_transfers: Option>, + pub transaction_error: Option, + pub instructions: Vec, + pub events: TransactionEvent, + pub timestamp: u64, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct AccountData { + pub account: String, + pub native_token_balance: Number, + pub token_balance_changes: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TokenBalanceChange { + pub user_account: String, + pub token_account: String, + pub raw_token_amount: RawTokenAmount, + pub mint: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RawTokenAmount { + pub token_amount: String, + pub decimals: Number, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct NativeTransfer { + #[serde(rename = "userAccounts", flatten)] + pub user_accounts: TransferUserAccounts, + pub amount: Number, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransferUserAccounts { + pub from_user_account: Option, + pub to_user_account: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TokenTransfer { + #[serde(flatten)] + pub user_accounts: TransferUserAccounts, + pub from_token_account: Option, + pub to_token_account: Option, + pub token_amount: Number, + pub token_standard: TokenStandard, + pub mint: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransactionError { + #[serde(rename = "InstructionError")] + pub instruciton_error: serde_json::Value, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Instruction { + pub accounts: Vec, + pub data: String, + #[serde(rename = "programId")] + pub program_id: String, + #[serde(rename = "innerInstructions")] + pub inner_instructions: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InnerInstruction { + pub accounts: Vec, + pub data: String, + #[serde(rename = "programId")] + pub program_id: String, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct TransactionEvent { + pub nft: Option, + pub swap: Option, + pub compressed: Option>, + #[serde(rename = "setAuthority")] + pub set_authority: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct NftEvent { + pub seller: String, + pub buyer: String, + pub timestamp: Number, + pub amount: Number, + pub fee: Number, + pub signature: String, + pub source: Source, + #[serde(rename = "type")] + pub transaction_type: TransactionType, + pub sale_type: TransactionContext, + pub nfts: Vec, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct SwapEvent { + pub native_input: Option, + pub native_output: Option, + pub token_inputs: Vec, + pub token_outputs: Vec, + pub token_fees: Vec, + pub native_fees: Vec, + pub inner_swaps: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Token { + pub mint: String, + #[serde(rename = "tokenStandard")] + pub token_standard: TokenStandard, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TokenSwap { + pub native_input: Option, + pub native_output: Option, + pub token_inputs: Vec, + pub token_outputs: Vec, + pub token_fees: Vec, + pub native_fees: Vec, + pub program_info: ProgramInfo, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct NativeBalanceChange { + pub account: String, + #[serde(deserialize_with = "deserialize_str_to_number")] + pub amount: Number, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProgramInfo { + pub source: Source, + pub account: String, + #[serde(rename = "programName")] + pub program_name: ProgramName, + #[serde(rename = "instructionName")] + pub instruction_name: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Authority { + pub account: String, + pub from: String, + pub to: String, + #[serde(rename = "instructionIndex")] + pub instruction_index: Option, + #[serde(rename = "innerInstructionIndex")] + pub inner_instruction_index: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CompressedNftEvent { + #[serde(rename = "type")] + pub transaction_type: TransactionType, + pub tree_id: String, + pub leaf_index: Option, + pub seq: Option, + pub asset_id: Option, + pub instruction_index: Option, + pub inner_instruction_index: Option, + pub new_leaf_owner: Option, + pub old_leaf_owner: Option, + pub new_leaf_delegate: Option, + pub old_leaf_delegate: Option, + pub tree_delegate: Option, + pub metadata: Option, + pub update_args: Option, +} diff --git a/src/types/enums.rs b/src/types/enums.rs index 193d898..37592c2 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use serde_enum_str::{Deserialize_enum_str, Serialize_enum_str}; use super::*; @@ -170,3 +171,521 @@ pub enum UiTransactionEncoding { Json, JsonParsed, } + +/// Enhanced Transaction Types +#[derive(Clone, Debug, PartialEq, Eq, Deserialize_enum_str, Serialize_enum_str)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum TransactionType { + AcceptEscrowArtist, + AcceptEscrowUser, + AcceptRequestArtist, + ActivateTransaction, + ActivateVault, + AddInstruction, + AddItem, + AddRaritiesToBank, + AddTokenToVault, + AddToPool, + AddToWhitelist, + Any, + ApproveTransaction, + AttachMetadata, + AuctionHouseCreate, + AuctionManagerClaimBid, + AuthorizeFunder, + BorrowFox, + BorrowSolForNft, + Burn, + BurnNft, + BuyItem, + BuySubscription, + BuyTickets, + CancelEscrow, + CancelLoanRequest, + CancelOffer, + CancelOrder, + CancelReward, + CancelSwap, + CancelTransaction, + CandyMachineRoute, + CandyMachineUnwrap, + CandyMachineUpdate, + CandyMachineWrap, + ChangeComicState, + ClaimNft, + ClaimRewards, + CloseAccount, + CloseEscrowAccount, + CloseItem, + CloseOrder, + ClosePosition, + CompressedNftBurn, + CompressedNftCancelRedeem, + CompressedNftDelegate, + CompressedNftMint, + CompressedNftRedeem, + CompressedNftSetVerifyCollection, + CompressedNftTransfer, + CompressedNftUnverifyCollection, + CompressedNftUnverifyCreator, + CompressedNftVerifyCollection, + CompressedNftVerifyCreator, + CompressNft, + CreateAppraisal, + CreateBet, + CreateEscrow, + CreateMasterEdition, + CreateMerkleTree, + CreateOrder, + CreatePool, + CreateRaffle, + CreateStore, + CreateTransaction, + DeauthorizeFunder, + DecompressNft, + DelegateMerkleTree, + DelistItem, + Deposit, + DepositFractionalPool, + DepositGem, + DistributeCompressionRewards, + EmptyPaymentAccount, + ExecuteTransaction, + FillOrder, + FinalizeProgramInstruction, + ForecloseLoan, + Fractionalize, + FundReward, + Fuse, + InitAuctionManagerV2, + InitBank, + InitFarm, + InitFarmer, + InitializeAccount, + InitRent, + InitStake, + InitSwap, + InitVault, + KickItem, + LendForNft, + ListItem, + Loan, + LoanFox, + LockReward, + MergeStake, + MigrateToPnft, + NftAuctionCancelled, + NftAuctionCreated, + NftAuctionUpdated, + NftBid, + NftBidCancelled, + NftCancelListing, + NftGlobalBid, + NftGlobalBidCancelled, + NftListing, + NftMint, + NftMintRejected, + NftParticipationReward, + NftRentActivate, + NftRentCancelListing, + NftRentEnd, + NftRentListing, + NftRentUpdateListing, + NftSale, + OfferLoan, + Payout, + PlaceBet, + PlaceSolBet, + PlatformFee, + ReborrowSolForNft, + RecordRarityPoints, + RefreshFarmer, + RejectSwap, + RejectTransaction, + RemoveFromPool, + RemoveFromWhitelist, + RepayLoan, + RequestLoan, + RequestPnftMigration, + RescindLoan, + SetAuthority, + SetBankFlags, + SetVaultLock, + SplitStake, + StakeSol, + StakeToken, + StartPnftMigration, + Swap, + SwitchFox, + SwitchFoxRequest, + TakeLoan, + TokenMint, + Transfer, + Unknown, + Unlabeled, + UnstakeSol, + UnstakeToken, + UpdateBankManager, + UpdateExternalPriceAccount, + UpdateFarm, + UpdateItem, + UpdateOffer, + UpdateOrder, + UpdatePrimarySaleMetadata, + UpdateRaffle, + UpdateRecordAuthorityData, + UpdateVaultOwner, + UpgradeFox, + UpgradeFoxRequest, + UpgradeProgramInstruction, + ValidateSafetyDepositBoxV2, + WhitelistCreator, + Withdraw, + WithdrawGem, + #[serde(other)] + Other(String), +} + +impl TransactionType { + pub fn all() -> Vec { + vec![ + Self::AcceptEscrowArtist, + Self::AcceptEscrowUser, + Self::AcceptRequestArtist, + Self::ActivateTransaction, + Self::ActivateVault, + Self::AddInstruction, + Self::AddItem, + Self::AddRaritiesToBank, + Self::AddTokenToVault, + Self::AddToPool, + Self::AddToWhitelist, + Self::Any, + Self::ApproveTransaction, + Self::AttachMetadata, + Self::AuctionHouseCreate, + Self::AuctionManagerClaimBid, + Self::AuthorizeFunder, + Self::BorrowFox, + Self::BorrowSolForNft, + Self::Burn, + Self::BurnNft, + Self::BuyItem, + Self::BuySubscription, + Self::BuyTickets, + Self::CancelEscrow, + Self::CancelLoanRequest, + Self::CancelOffer, + Self::CancelOrder, + Self::CancelReward, + Self::CancelSwap, + Self::CancelTransaction, + Self::CandyMachineRoute, + Self::CandyMachineUnwrap, + Self::CandyMachineUpdate, + Self::CandyMachineWrap, + Self::ChangeComicState, + Self::ClaimNft, + Self::ClaimRewards, + Self::CloseAccount, + Self::CloseEscrowAccount, + Self::CloseItem, + Self::CloseOrder, + Self::ClosePosition, + Self::CompressedNftBurn, + Self::CompressedNftCancelRedeem, + Self::CompressedNftDelegate, + Self::CompressedNftMint, + Self::CompressedNftRedeem, + Self::CompressedNftSetVerifyCollection, + Self::CompressedNftTransfer, + Self::CompressedNftUnverifyCollection, + Self::CompressedNftUnverifyCreator, + Self::CompressedNftVerifyCollection, + Self::CompressedNftVerifyCreator, + Self::CompressNft, + Self::CreateAppraisal, + Self::CreateBet, + Self::CreateEscrow, + Self::CreateMasterEdition, + Self::CreateMerkleTree, + Self::CreateOrder, + Self::CreatePool, + Self::CreateRaffle, + Self::CreateStore, + Self::CreateTransaction, + Self::DeauthorizeFunder, + Self::DecompressNft, + Self::DelegateMerkleTree, + Self::DelistItem, + Self::Deposit, + Self::DepositFractionalPool, + Self::DepositGem, + Self::DistributeCompressionRewards, + Self::EmptyPaymentAccount, + Self::ExecuteTransaction, + Self::FillOrder, + Self::FinalizeProgramInstruction, + Self::ForecloseLoan, + Self::Fractionalize, + Self::FundReward, + Self::Fuse, + Self::InitAuctionManagerV2, + Self::InitBank, + Self::InitFarm, + Self::InitFarmer, + Self::InitializeAccount, + Self::InitRent, + Self::InitStake, + Self::InitSwap, + Self::InitVault, + Self::KickItem, + Self::LendForNft, + Self::ListItem, + Self::Loan, + Self::LoanFox, + Self::LockReward, + Self::MergeStake, + Self::MigrateToPnft, + Self::NftAuctionCancelled, + Self::NftAuctionCreated, + Self::NftAuctionUpdated, + Self::NftBid, + Self::NftBidCancelled, + Self::NftCancelListing, + Self::NftGlobalBid, + Self::NftGlobalBidCancelled, + Self::NftListing, + Self::NftMint, + Self::NftMintRejected, + Self::NftParticipationReward, + Self::NftRentActivate, + Self::NftRentCancelListing, + Self::NftRentEnd, + Self::NftRentListing, + Self::NftRentUpdateListing, + Self::NftSale, + Self::OfferLoan, + Self::Payout, + Self::PlaceBet, + Self::PlaceSolBet, + Self::PlatformFee, + Self::ReborrowSolForNft, + Self::RecordRarityPoints, + Self::RefreshFarmer, + Self::RejectSwap, + Self::RejectTransaction, + Self::RemoveFromPool, + Self::RemoveFromWhitelist, + Self::RepayLoan, + Self::RequestLoan, + Self::RequestPnftMigration, + Self::RescindLoan, + Self::SetAuthority, + Self::SetBankFlags, + Self::SetVaultLock, + Self::SplitStake, + Self::StakeSol, + Self::StakeToken, + Self::StartPnftMigration, + Self::Swap, + Self::SwitchFox, + Self::SwitchFoxRequest, + Self::TakeLoan, + Self::TokenMint, + Self::Transfer, + Self::Unknown, + Self::Unlabeled, + Self::UnstakeSol, + Self::UnstakeToken, + Self::UpdateBankManager, + Self::UpdateExternalPriceAccount, + Self::UpdateFarm, + Self::UpdateItem, + Self::UpdateOffer, + Self::UpdateOrder, + Self::UpdatePrimarySaleMetadata, + Self::UpdateRaffle, + Self::UpdateRecordAuthorityData, + Self::UpdateVaultOwner, + Self::UpgradeFox, + Self::UpgradeFoxRequest, + Self::UpgradeProgramInstruction, + Self::ValidateSafetyDepositBoxV2, + Self::WhitelistCreator, + Self::Withdraw, + Self::WithdrawGem, + ] + } +} + +#[derive(Clone, Debug, Eq, PartialEq, Deserialize_enum_str, Serialize_enum_str)] +#[allow(non_camel_case_types)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Source { + FormFunction, + ExchangeArt, + CandyMachineV3, + CandyMachineV2, + CandyMachineV1, + Unknown, + Solanart, + Solsea, + MagicEden, + Holaplex, + Metaplex, + Opensea, + SolanaProgramLibrary, + Anchor, + Phantom, + SystemProgram, + StakeProgram, + Coinbase, + CoralCube, + Hedge, + LaunchMyNft, + GemBank, + GemFarm, + Degods, + Bsl, + Yawww, + Atadia, + DigitalEyes, + Hyperspace, + Tensor, + Bifrost, + Jupiter, + Mecurial, + Saber, + Serum, + StepFinance, + Cropper, + Raydium, + Aldrin, + Crema, + Lifinity, + Cykura, + Orca, + Marinade, + Stepn, + Sencha, + Saros, + EnglishAuction, + Foxy, + Hadeswap, + FoxyStaking, + FoxyRaffle, + FoxyTokenMarket, + FoxyMissions, + FoxyMarmalade, + FoxyCoinflip, + FoxyAuction, + Citrus, + Zeta, + Elixir, + ElixirLaunchpad, + CardinalRent, + CardinalStaking, + BpfLoader, + BpfUpgradeableLoader, + Squads, + SharkyFi, + OpenCreatorProtocol, + Bubblegum, + W_SOL, + DUST, + SOLI, + USDC, + FLWR, + HDG, + MEAN, + UXD, + SHDW, + POLIS, + ATLAS, + USH, + TRTLS, + RUNNER, + INVICTUS, + #[serde(other)] + Other(String), +} + +#[derive(Clone, Debug, Eq, PartialEq, Deserialize_enum_str, Serialize_enum_str)] +pub enum TokenStandard { + Fungible, + FungibleAsset, + NonFungible, + NonFungibleEdition, + ProgrammableNonFungible, + UnknownStandard, + #[serde(other)] + Other(String), +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize_enum_str, Deserialize_enum_str)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum TransactionContext { + Auction, + InstantSale, + Offer, + GlobalOffer, + Mint, + Unknown, + #[serde(other)] + Other(String), +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize_enum_str, Deserialize_enum_str)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum ProgramName { + Unkown, + JupiterV1, + JupiterV2, + JupiterV3, + JupiterV4, + MercurialStableSwap, + SaberStableSwap, + SaberExchange, + SerumDexV1, + SerumDexV2, + SerumDexV3, + SerumSwap, + StepFinance, + Cropper, + RaydiumLiquidityPoolV2, + RaydiumLiquidityPoolV3, + RaydiumLiquidityPoolV4, + AldrinAmmV1, + AldrinAmmV2, + Crema, + Lifinity, + LifinityV2, + Cykura, + OrcaTokenSwapV1, + OrcaTokenSwapV2, + OrcaWhirlpools, + Marinade, + Stepn, + SenchaExchange, + SarosAmm, + FoxyStake, + FoxySwap, + FoxyRaffle, + FoxyTokenMarket, + FoxyMissions, + FoxyMarmalade, + FoxyCoinflip, + FoxyAuction, + Citrus, + HadeSwap, + Zeta, + CardinalRent, + CardinalStaking, + SharkyFi, + OpenCreatorProtocol, + Bubblegum, + CoralCube, + #[serde(other)] + Other(String), +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 95ec493..ff34990 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,7 +1,9 @@ +pub mod enhanced_transaction_types; pub mod enums; pub mod options; pub mod types; +pub use self::enhanced_transaction_types::*; pub use self::enums::*; pub use self::options::*; pub use self::types::*; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 2714985..9993e6f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,5 @@ +pub use self::deserialize_str_to_number::deserialize_str_to_number; pub use self::is_valid_solana_address::is_valid_solana_address; +mod deserialize_str_to_number; mod is_valid_solana_address; diff --git a/tests/tests.rs b/tests/tests.rs index 37bde4a..4006cfe 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,4 +1,5 @@ mod utils { + mod test_deserialize_str_to_number; mod test_is_valid_solana_address; }