diff --git a/Cargo.lock b/Cargo.lock index e5d4302..601cf02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,9 +429,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" [[package]] name = "cfg-if" @@ -755,9 +755,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.133" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libsecp256k1" @@ -1125,9 +1125,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "solana-frozen-abi" -version = "1.9.29" +version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d4fcb89eb3d0f30bd4b4a31ad1825c9d95cd638509acead00969d7601713288" +checksum = "a5f69a79200f5ba439eb8b790c5e00beab4d1fae4da69ce023c69c6ac1b55bf1" dependencies = [ "bs58 0.4.0", "bv", @@ -1145,9 +1145,9 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.9.29" +version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d63ab101db88ecccd8da34065b9097b88367e0744fdfd05cb7de87b4ede3717f" +checksum = "402fffb54bf5d335e6df26fc1719feecfbd7a22fafdf6649fe78380de3c47384" dependencies = [ "proc-macro2", "quote", @@ -1157,9 +1157,9 @@ dependencies = [ [[package]] name = "solana-logger" -version = "1.9.29" +version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1805d52fc8277a84c4803c7850c8f41471b57fb0dec7750338955ad6e43e2" +checksum = "942dc59fc9da66d178362051b658646b65dc11cea0bc804e4ecd2528d3c1279f" dependencies = [ "env_logger", "lazy_static", @@ -1168,9 +1168,9 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.9.29" +version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5deafc4902425d40197f74166640300dd20b078e4ffd518c1bb56ceb7e01680" +checksum = "0a463f546a2f5842d35974bd4691ae5ceded6785ec24db440f773723f6ce4e11" dependencies = [ "base64 0.13.0", "bincode", @@ -1211,9 +1211,9 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.9.29" +version = "1.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db4c93bd43c91290ad54fe6ff86179a859954f196507c4789a4876d38a62f17" +checksum = "c834b4e02ac911b13c13aed08b3f847e722f6be79d31b1c660c1dbd2dee83cdb" dependencies = [ "bs58 0.4.0", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index c79c053..9d9341b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,4 @@ [workspace] members = ["crates/*", "examples/*"] +# exclude +exclude = ["examples/drift"] diff --git a/README.md b/README.md index 2c15b47..3a225c8 100644 --- a/README.md +++ b/README.md @@ -19,27 +19,85 @@ License: Apache-2.0 ## Example ```rust -anchor_gen::generate_cpi_crate("path/to/idl.json"); -// I'm using this crate under the alias "drift_cpi" since there are many programs using this macro -// which all export the same InstructionType/AccountType enum - -// data from a transaction instruction -let data: Vec = [1,2,3,4,4,5,1,3,4,1,3,4,2,4]; -let ix: drift_cpi::InstructionType = drift_cpi::InstructionType::decode(&data[..])?; -match ix { -drift_cpi::InstructionType::PlacePerpOrder(ix) => {}, -drift_cpi::InstructionType::CancelOrders(ix) => {}, -drift_cpi::InstructionType::PlaceAndTakePerpOrder(ix) => {}, -_ => { // 50 other ix types... } -}; - -let acct: solana_sdk::account::Account = rpc.get_account(&key).await?; -let data: Vec = acct.data; -let ix: drift_cpi::AccounType = drift_cpi::AccountType::decode(&data[..])?; -match ix { -drift_cpi::AccountType::User(user) => {}, -drift_cpi::AccountType::PerpMarket(market) => {}, -drift_cpi::AccountType::SpotMarket(market) => {}, -_ => { // 10 other account types... } -}; +use solana_sdk::bs58; +use solana_transaction_status::{UiInstruction, UiMessage, UiParsedInstruction}; +use anchor_gen::prelude::*; + +generate_cpi_crate!("idl.json"); +declare_id!("dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH"); + + +#[test] +fn accounts() -> anyhow::Result<()> { + let rpc = solana_client::rpc_client::RpcClient::new("https://api.mainnet-beta.solana.com".to_string()); + let key = solana_sdk::pubkey!("H5jfagEnMVNH3PMc2TU2F7tNuXE6b4zCwoL5ip1b4ZHi"); + let acct = rpc.get_account(&key)?; + let data: Vec = acct.data; + let ix: AccountType = AccountType::decode(&data[..]).map_err( + |e| anyhow::anyhow!("Failed to decode account: {:?}", e) + )?; + match ix { + AccountType::User(user) => println!("{}", user.settled_perp_pnl), + AccountType::PerpMarket(market) => println!("{}", market.amm.oracle), + AccountType::SpotMarket(market) => println!("{}", market.flash_loan_amount), + _ => {} + } + Ok(()) +} + +#[test] +fn instructions() -> anyhow::Result<()> { + use std::str::FromStr; + use solana_transaction_status::UiTransactionEncoding; + use solana_transaction_status::EncodedTransaction; + + let rpc = solana_client::rpc_client::RpcClient::new("https://api.mainnet-beta.solana.com".to_string()); + let key = solana_sdk::pubkey!("H5jfagEnMVNH3PMc2TU2F7tNuXE6b4zCwoL5ip1b4ZHi"); + let results = rpc.get_signatures_for_address(&key)?; + if !results.is_empty() { + let result = results[0].clone(); + let signature = solana_sdk::signature::Signature::from_str(&result.signature)?; + let tx = rpc.get_transaction(&signature, UiTransactionEncoding::JsonParsed)?; + if let EncodedTransaction::Json(tx) = tx.transaction.transaction { + if let UiMessage::Parsed(msg) = tx.message { + for ui_ix in msg.instructions { + if let UiInstruction::Parsed(ui_parsed_ix) = ui_ix { + match ui_parsed_ix { + UiParsedInstruction::Parsed(parsed_ix) => { + println!("parsed ix for program \"{}\": {:#?}", parsed_ix.program, parsed_ix.parsed) + } + UiParsedInstruction::PartiallyDecoded(ui_decoded_ix) => { + let data: Vec = bs58::decode(ui_decoded_ix.data.clone()).into_vec()?; + // only match instruction if it belongs to the IDL that generated this crate (the Drift program) + if data.len() >= 8 && ui_decoded_ix.program_id == id().to_string() { + if let Ok(discrim) = data[..8].try_into() { + let ix = InstructionType::decode(&data[..]).map_err( + |e| anyhow::anyhow!("Failed to decode instruction: {:?}", e) + )?; + let name = InstructionType::discrim_to_name(discrim).unwrap(); + match ix { + InstructionType::PlacePerpOrder(ix) => { + println!("{}, {:#?}", name, ix._params); + } + InstructionType::PlaceAndTakePerpOrder(ix) => { + println!("{}, {:#?}", name, ix._params); + } + InstructionType::PlaceOrders(ix) => { + for params in ix._params { + println!("{}, {:#?}", name, params); + } + } + _ => {} + } + } + } + } + } + } + } + } + } + } + Ok(()) +} ``` \ No newline at end of file diff --git a/crates/anchor-idl/src/program.rs b/crates/anchor-idl/src/program.rs index 472fc56..4498cee 100644 --- a/crates/anchor-idl/src/program.rs +++ b/crates/anchor-idl/src/program.rs @@ -7,7 +7,7 @@ use std::{ // use anchor_lang::solana_program::hash::hash; use darling::{util::PathList, FromMeta}; -use heck::{ToPascalCase, ToSnakeCase}; +use heck::ToPascalCase; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote};