From 3f6f1adb5be60b6bc6c46c30a9cd2b6f133b7fad Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Mon, 3 Aug 2020 14:27:15 -0600 Subject: [PATCH] Make accounts explicit in unrecognized jsonParsed instructions (#11351) --- transaction-status/src/lib.rs | 33 ++++++++++++++++++++++-- transaction-status/src/parse_accounts.rs | 18 ++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 26f94c6259..8da45292ba 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -8,12 +8,13 @@ pub mod parse_instruction; pub mod parse_token; use crate::{parse_accounts::parse_accounts, parse_instruction::parse}; -use serde_json::Value; +use serde_json::{json, Value}; use solana_sdk::{ clock::{Slot, UnixTimestamp}, commitment_config::CommitmentConfig, instruction::CompiledInstruction, message::MessageHeader, + pubkey::Pubkey, transaction::{Result, Transaction, TransactionError}, }; @@ -44,6 +45,29 @@ impl From<&CompiledInstruction> for UiCompiledInstruction { } } +/// A partially decoded CompiledInstruction that includes explicit account addresses +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UiPartiallyDecodedInstruction { + pub program_id: String, + pub accounts: Vec, + pub data: String, +} + +impl UiPartiallyDecodedInstruction { + fn from(instruction: &CompiledInstruction, account_keys: &[Pubkey]) -> Self { + Self { + program_id: account_keys[instruction.program_id_index as usize].to_string(), + accounts: instruction + .accounts + .iter() + .map(|&i| account_keys[i as usize].to_string()) + .collect(), + data: bs58::encode(instruction.data.clone()).into_string(), + } + } +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransactionStatusMeta { @@ -228,7 +252,12 @@ impl EncodedTransaction { ) { UiInstruction::Parsed(parsed_instruction) } else { - UiInstruction::Compiled(instruction.into()) + UiInstruction::Parsed(json!( + UiPartiallyDecodedInstruction::from( + instruction, + &transaction.message.account_keys + ) + )) } }) .collect(), diff --git a/transaction-status/src/parse_accounts.rs b/transaction-status/src/parse_accounts.rs index 71ef7bf91e..6f3fc59d42 100644 --- a/transaction-status/src/parse_accounts.rs +++ b/transaction-status/src/parse_accounts.rs @@ -1,4 +1,4 @@ -use serde_json::{json, Value}; +use serde_json::{json, Map, Value}; use solana_sdk::message::Message; type AccountAttributes = Vec; @@ -11,7 +11,7 @@ enum AccountAttribute { } pub fn parse_accounts(message: &Message) -> Value { - let mut accounts: Vec = vec![]; + let mut accounts: Map = Map::new(); for (i, account_key) in message.account_keys.iter().enumerate() { let mut attributes: AccountAttributes = vec![]; if message.is_writable(i) { @@ -20,7 +20,7 @@ pub fn parse_accounts(message: &Message) -> Value { if message.is_signer(i) { attributes.push(AccountAttribute::Signer); } - accounts.push(json!({ account_key.to_string(): attributes })); + accounts.insert(account_key.to_string(), json!(attributes)); } json!(accounts) } @@ -44,12 +44,12 @@ mod test { }; message.account_keys = vec![pubkey0, pubkey1, pubkey2, pubkey3]; - let expected_json = json!([ - {pubkey0.to_string(): ["writable", "signer"]}, - {pubkey1.to_string(): ["signer"]}, - {pubkey2.to_string(): ["writable"]}, - {pubkey3.to_string(): []}, - ]); + let expected_json = json!({ + pubkey0.to_string(): ["writable", "signer"], + pubkey1.to_string(): ["signer"], + pubkey2.to_string(): ["writable"], + pubkey3.to_string(): [], + }); assert_eq!(parse_accounts(&message), expected_json); }