Update instruction encoding format (#11363)

* Rework parsed instruction format

* Rework parsed message accounts

* Review comments
This commit is contained in:
Tyera Eulberg
2020-08-05 00:58:58 -06:00
committed by GitHub
parent 86e3f96f16
commit 9d4f9be1fe
4 changed files with 264 additions and 173 deletions

View File

@ -7,8 +7,10 @@ pub mod parse_accounts;
pub mod parse_instruction; pub mod parse_instruction;
pub mod parse_token; pub mod parse_token;
use crate::{parse_accounts::parse_accounts, parse_instruction::parse}; use crate::{
use serde_json::{json, Value}; parse_accounts::{parse_accounts, ParsedAccount},
parse_instruction::{parse, ParsedInstruction},
};
use solana_sdk::{ use solana_sdk::{
clock::{Slot, UnixTimestamp}, clock::{Slot, UnixTimestamp},
commitment_config::CommitmentConfig, commitment_config::CommitmentConfig,
@ -23,7 +25,14 @@ use solana_sdk::{
#[serde(rename_all = "camelCase", untagged)] #[serde(rename_all = "camelCase", untagged)]
pub enum UiInstruction { pub enum UiInstruction {
Compiled(UiCompiledInstruction), Compiled(UiCompiledInstruction),
Parsed(Value), Parsed(UiParsedInstruction),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", untagged)]
pub enum UiParsedInstruction {
Parsed(ParsedInstruction),
PartiallyDecoded(UiPartiallyDecodedInstruction),
} }
/// A duplicate representation of a CompiledInstruction for pretty JSON serialization /// A duplicate representation of a CompiledInstruction for pretty JSON serialization
@ -183,7 +192,7 @@ pub struct UiRawMessage {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UiParsedMessage { pub struct UiParsedMessage {
pub account_keys: Value, pub account_keys: Vec<ParsedAccount>,
pub recent_blockhash: String, pub recent_blockhash: String,
pub instructions: Vec<UiInstruction>, pub instructions: Vec<UiInstruction>,
} }
@ -250,13 +259,15 @@ impl EncodedTransaction {
instruction, instruction,
&transaction.message.account_keys, &transaction.message.account_keys,
) { ) {
UiInstruction::Parsed(parsed_instruction) UiInstruction::Parsed(UiParsedInstruction::Parsed(
parsed_instruction,
))
} else { } else {
UiInstruction::Parsed(json!( UiInstruction::Parsed(UiParsedInstruction::PartiallyDecoded(
UiPartiallyDecodedInstruction::from( UiPartiallyDecodedInstruction::from(
instruction, instruction,
&transaction.message.account_keys &transaction.message.account_keys,
) ),
)) ))
} }
}) })

View File

@ -1,28 +1,23 @@
use serde_json::{json, Map, Value};
use solana_sdk::message::Message; use solana_sdk::message::Message;
type AccountAttributes = Vec<AccountAttribute>; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
enum AccountAttribute { pub struct ParsedAccount {
Signer, pub pubkey: String,
Writable, pub writable: bool,
pub signer: bool,
} }
pub fn parse_accounts(message: &Message) -> Value { pub fn parse_accounts(message: &Message) -> Vec<ParsedAccount> {
let mut accounts: Map<String, Value> = Map::new(); let mut accounts: Vec<ParsedAccount> = vec![];
for (i, account_key) in message.account_keys.iter().enumerate() { for (i, account_key) in message.account_keys.iter().enumerate() {
let mut attributes: AccountAttributes = vec![]; accounts.push(ParsedAccount {
if message.is_writable(i) { pubkey: account_key.to_string(),
attributes.push(AccountAttribute::Writable); writable: message.is_writable(i),
signer: message.is_signer(i),
});
} }
if message.is_signer(i) { accounts
attributes.push(AccountAttribute::Signer);
}
accounts.insert(account_key.to_string(), json!(attributes));
}
json!(accounts)
} }
#[cfg(test)] #[cfg(test)]
@ -44,13 +39,30 @@ mod test {
}; };
message.account_keys = vec![pubkey0, pubkey1, pubkey2, pubkey3]; message.account_keys = vec![pubkey0, pubkey1, pubkey2, pubkey3];
let expected_json = json!({ assert_eq!(
pubkey0.to_string(): ["writable", "signer"], parse_accounts(&message),
pubkey1.to_string(): ["signer"], vec![
pubkey2.to_string(): ["writable"], ParsedAccount {
pubkey3.to_string(): [], pubkey: pubkey0.to_string(),
}); writable: true,
signer: true,
assert_eq!(parse_accounts(&message), expected_json); },
ParsedAccount {
pubkey: pubkey1.to_string(),
writable: false,
signer: true,
},
ParsedAccount {
pubkey: pubkey2.to_string(),
writable: true,
signer: false,
},
ParsedAccount {
pubkey: pubkey3.to_string(),
writable: false,
signer: false,
},
]
);
} }
} }

View File

@ -1,6 +1,6 @@
use crate::parse_token::parse_token; use crate::parse_token::parse_token;
use inflector::Inflector; use inflector::Inflector;
use serde_json::{json, Value}; use serde_json::Value;
use solana_account_decoder::parse_token::spl_token_id_v1_0; use solana_account_decoder::parse_token::spl_token_id_v1_0;
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey}; use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
use std::{ use std::{
@ -21,7 +21,7 @@ lazy_static! {
}; };
} }
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug)]
pub enum ParseInstructionError { pub enum ParseInstructionError {
#[error("{0:?} instruction not parsable")] #[error("{0:?} instruction not parsable")]
InstructionNotParsable(ParsableProgram), InstructionNotParsable(ParsableProgram),
@ -31,6 +31,25 @@ pub enum ParseInstructionError {
#[error("Program not parsable")] #[error("Program not parsable")]
ProgramNotParsable, ProgramNotParsable,
#[error("Internal error, please report")]
SerdeJsonError(#[from] serde_json::error::Error),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ParsedInstruction {
pub program: String,
pub program_id: String,
pub parsed: Value,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ParsedInstructionEnum {
#[serde(rename = "type")]
pub instruction_type: String,
pub info: Value,
} }
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
@ -44,17 +63,19 @@ pub fn parse(
program_id: &Pubkey, program_id: &Pubkey,
instruction: &CompiledInstruction, instruction: &CompiledInstruction,
account_keys: &[Pubkey], account_keys: &[Pubkey],
) -> Result<Value, ParseInstructionError> { ) -> Result<ParsedInstruction, ParseInstructionError> {
let program_name = PARSABLE_PROGRAM_IDS let program_name = PARSABLE_PROGRAM_IDS
.get(program_id) .get(program_id)
.ok_or_else(|| ParseInstructionError::ProgramNotParsable)?; .ok_or_else(|| ParseInstructionError::ProgramNotParsable)?;
let parsed_json = match program_name { let parsed_json = match program_name {
ParsableProgram::SplMemo => parse_memo(instruction), ParsableProgram::SplMemo => parse_memo(instruction),
ParsableProgram::SplToken => parse_token(instruction, account_keys)?, ParsableProgram::SplToken => serde_json::to_value(parse_token(instruction, account_keys)?)?,
}; };
Ok(json!({ Ok(ParsedInstruction {
format!("{:?}", program_name).to_kebab_case(): parsed_json program: format!("{:?}", program_name).to_kebab_case(),
})) program_id: program_id.to_string(),
parsed: parsed_json,
})
} }
fn parse_memo(instruction: &CompiledInstruction) -> Value { fn parse_memo(instruction: &CompiledInstruction) -> Value {
@ -64,6 +85,7 @@ fn parse_memo(instruction: &CompiledInstruction) -> Value {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use serde_json::json;
#[test] #[test]
fn test_parse() { fn test_parse() {
@ -72,18 +94,16 @@ mod test {
accounts: vec![], accounts: vec![],
data: vec![240, 159, 166, 150], data: vec![240, 159, 166, 150],
}; };
let expected_json = json!({
"spl-memo": "🦖"
});
assert_eq!( assert_eq!(
parse(&MEMO_PROGRAM_ID, &memo_instruction, &[]).unwrap(), parse(&MEMO_PROGRAM_ID, &memo_instruction, &[]).unwrap(),
expected_json ParsedInstruction {
program: "spl-memo".to_string(),
program_id: MEMO_PROGRAM_ID.to_string(),
parsed: json!("🦖"),
}
); );
let non_parsable_program_id = Pubkey::new(&[1; 32]); let non_parsable_program_id = Pubkey::new(&[1; 32]);
assert_eq!( assert!(parse(&non_parsable_program_id, &memo_instruction, &[]).is_err());
parse(&non_parsable_program_id, &memo_instruction, &[]).unwrap_err(),
ParseInstructionError::ProgramNotParsable
);
} }
} }

View File

@ -1,4 +1,4 @@
use crate::parse_instruction::{ParsableProgram, ParseInstructionError}; use crate::parse_instruction::{ParsableProgram, ParseInstructionError, ParsedInstructionEnum};
use serde_json::{json, Map, Value}; use serde_json::{json, Map, Value};
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey}; use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
use spl_token_v1_0::instruction::TokenInstruction; use spl_token_v1_0::instruction::TokenInstruction;
@ -6,7 +6,7 @@ use spl_token_v1_0::instruction::TokenInstruction;
pub fn parse_token( pub fn parse_token(
instruction: &CompiledInstruction, instruction: &CompiledInstruction,
account_keys: &[Pubkey], account_keys: &[Pubkey],
) -> Result<Value, ParseInstructionError> { ) -> Result<ParsedInstructionEnum, ParseInstructionError> {
let token_instruction = TokenInstruction::unpack(&instruction.data) let token_instruction = TokenInstruction::unpack(&instruction.data)
.map_err(|_| ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken))?; .map_err(|_| ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken))?;
if instruction.accounts.len() > account_keys.len() { if instruction.accounts.len() > account_keys.len() {
@ -23,7 +23,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "initializeMint",
"mint": account_keys[instruction.accounts[0] as usize].to_string(), "mint": account_keys[instruction.accounts[0] as usize].to_string(),
"amount": amount, "amount": amount,
"decimals":decimals, "decimals":decimals,
@ -46,7 +45,10 @@ pub fn parse_token(
); );
} }
} }
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "initializeMint".to_string(),
info: value,
})
} }
TokenInstruction::InitializeAccount => { TokenInstruction::InitializeAccount => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -54,12 +56,14 @@ pub fn parse_token(
ParsableProgram::SplToken, ParsableProgram::SplToken,
)); ));
} }
Ok(json!({ Ok(ParsedInstructionEnum {
"type": "initializeAccount", instruction_type: "initializeAccount".to_string(),
info: json!({
"account": account_keys[instruction.accounts[0] as usize].to_string(), "account": account_keys[instruction.accounts[0] as usize].to_string(),
"mint": account_keys[instruction.accounts[1] as usize].to_string(), "mint": account_keys[instruction.accounts[1] as usize].to_string(),
"owner": account_keys[instruction.accounts[2] as usize].to_string(), "owner": account_keys[instruction.accounts[2] as usize].to_string(),
})) }),
})
} }
TokenInstruction::InitializeMultisig { m } => { TokenInstruction::InitializeMultisig { m } => {
if instruction.accounts.len() < 2 { if instruction.accounts.len() < 2 {
@ -71,12 +75,14 @@ pub fn parse_token(
for i in instruction.accounts[1..].iter() { for i in instruction.accounts[1..].iter() {
signers.push(account_keys[*i as usize].to_string()); signers.push(account_keys[*i as usize].to_string());
} }
Ok(json!({ Ok(ParsedInstructionEnum {
"type": "initializeMultisig", instruction_type: "initializeMultisig".to_string(),
info: json!({
"multisig": account_keys[instruction.accounts[0] as usize].to_string(), "multisig": account_keys[instruction.accounts[0] as usize].to_string(),
"signers": signers, "signers": signers,
"m": m, "m": m,
})) }),
})
} }
TokenInstruction::Transfer { amount } => { TokenInstruction::Transfer { amount } => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -85,7 +91,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "transfer",
"source": account_keys[instruction.accounts[0] as usize].to_string(), "source": account_keys[instruction.accounts[0] as usize].to_string(),
"destination": account_keys[instruction.accounts[1] as usize].to_string(), "destination": account_keys[instruction.accounts[1] as usize].to_string(),
"amount": amount, "amount": amount,
@ -99,7 +104,10 @@ pub fn parse_token(
"authority", "authority",
"multisigAuthority", "multisigAuthority",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "transfer".to_string(),
info: value,
})
} }
TokenInstruction::Approve { amount } => { TokenInstruction::Approve { amount } => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -108,7 +116,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "approve",
"source": account_keys[instruction.accounts[0] as usize].to_string(), "source": account_keys[instruction.accounts[0] as usize].to_string(),
"delegate": account_keys[instruction.accounts[1] as usize].to_string(), "delegate": account_keys[instruction.accounts[1] as usize].to_string(),
"amount": amount, "amount": amount,
@ -122,7 +129,10 @@ pub fn parse_token(
"owner", "owner",
"multisigOwner", "multisigOwner",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "approve".to_string(),
info: value,
})
} }
TokenInstruction::Revoke => { TokenInstruction::Revoke => {
if instruction.accounts.len() < 2 { if instruction.accounts.len() < 2 {
@ -131,7 +141,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "revoke",
"source": account_keys[instruction.accounts[0] as usize].to_string(), "source": account_keys[instruction.accounts[0] as usize].to_string(),
}); });
let mut map = value.as_object_mut().unwrap(); let mut map = value.as_object_mut().unwrap();
@ -143,7 +152,10 @@ pub fn parse_token(
"owner", "owner",
"multisigOwner", "multisigOwner",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "revoke".to_string(),
info: value,
})
} }
TokenInstruction::SetOwner => { TokenInstruction::SetOwner => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -152,7 +164,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "setOwner",
"owned": account_keys[instruction.accounts[0] as usize].to_string(), "owned": account_keys[instruction.accounts[0] as usize].to_string(),
"newOwner": account_keys[instruction.accounts[1] as usize].to_string(), "newOwner": account_keys[instruction.accounts[1] as usize].to_string(),
}); });
@ -165,7 +176,10 @@ pub fn parse_token(
"owner", "owner",
"multisigOwner", "multisigOwner",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "setOwner".to_string(),
info: value,
})
} }
TokenInstruction::MintTo { amount } => { TokenInstruction::MintTo { amount } => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -174,7 +188,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "mintTo",
"mint": account_keys[instruction.accounts[0] as usize].to_string(), "mint": account_keys[instruction.accounts[0] as usize].to_string(),
"account": account_keys[instruction.accounts[1] as usize].to_string(), "account": account_keys[instruction.accounts[1] as usize].to_string(),
"amount": amount, "amount": amount,
@ -188,7 +201,10 @@ pub fn parse_token(
"owner", "owner",
"multisigOwner", "multisigOwner",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "mintTo".to_string(),
info: value,
})
} }
TokenInstruction::Burn { amount } => { TokenInstruction::Burn { amount } => {
if instruction.accounts.len() < 2 { if instruction.accounts.len() < 2 {
@ -197,7 +213,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "burn",
"account": account_keys[instruction.accounts[0] as usize].to_string(), "account": account_keys[instruction.accounts[0] as usize].to_string(),
"amount": amount, "amount": amount,
}); });
@ -210,7 +225,10 @@ pub fn parse_token(
"authority", "authority",
"multisigAuthority", "multisigAuthority",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "burn".to_string(),
info: value,
})
} }
TokenInstruction::CloseAccount => { TokenInstruction::CloseAccount => {
if instruction.accounts.len() < 3 { if instruction.accounts.len() < 3 {
@ -219,7 +237,6 @@ pub fn parse_token(
)); ));
} }
let mut value = json!({ let mut value = json!({
"type": "closeAccount",
"account": account_keys[instruction.accounts[0] as usize].to_string(), "account": account_keys[instruction.accounts[0] as usize].to_string(),
"destination": account_keys[instruction.accounts[1] as usize].to_string(), "destination": account_keys[instruction.accounts[1] as usize].to_string(),
}); });
@ -232,7 +249,10 @@ pub fn parse_token(
"owner", "owner",
"multisigOwner", "multisigOwner",
); );
Ok(value) Ok(ParsedInstructionEnum {
instruction_type: "closeAccount".to_string(),
info: value,
})
} }
} }
} }
@ -311,14 +331,16 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "initializeMint", instruction_type: "initializeMint".to_string(),
info: json!({
"mint": keys[0].to_string(), "mint": keys[0].to_string(),
"amount": 42, "amount": 42,
"decimals": 2, "decimals": 2,
"account": keys[1].to_string(), "account": keys[1].to_string(),
"owner": keys[2].to_string(), "owner": keys[2].to_string(),
}) })
}
); );
let initialize_mint_ix = initialize_mint( let initialize_mint_ix = initialize_mint(
@ -334,13 +356,15 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "initializeMint", instruction_type: "initializeMint".to_string(),
info: json!({
"mint": keys[0].to_string(), "mint": keys[0].to_string(),
"amount": 42, "amount": 42,
"decimals": 2, "decimals": 2,
"account": keys[1].to_string(), "account": keys[1].to_string(),
}) })
}
); );
let initialize_mint_ix = initialize_mint( let initialize_mint_ix = initialize_mint(
@ -356,13 +380,15 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "initializeMint", instruction_type: "initializeMint".to_string(),
info: json!({
"mint": keys[0].to_string(), "mint": keys[0].to_string(),
"amount": 0, "amount": 0,
"decimals": 2, "decimals": 2,
"owner": keys[1].to_string(), "owner": keys[1].to_string(),
}) })
}
); );
// Test InitializeAccount // Test InitializeAccount
@ -377,12 +403,14 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "initializeAccount", instruction_type: "initializeAccount".to_string(),
info: json!({
"account": keys[0].to_string(), "account": keys[0].to_string(),
"mint": keys[1].to_string(), "mint": keys[1].to_string(),
"owner": keys[2].to_string(), "owner": keys[2].to_string(),
}) })
}
); );
// Test InitializeMultisig // Test InitializeMultisig
@ -401,12 +429,14 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "initializeMultisig", instruction_type: "initializeMultisig".to_string(),
info: json!({
"multisig": keys[0].to_string(), "multisig": keys[0].to_string(),
"m": 2, "m": 2,
"signers": keys[1..4].iter().map(|key| key.to_string()).collect::<Vec<String>>(), "signers": keys[1..4].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
}) })
}
); );
// Test Transfer, incl multisig // Test Transfer, incl multisig
@ -423,13 +453,15 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "transfer", instruction_type: "transfer".to_string(),
info: json!({
"source": keys[1].to_string(), "source": keys[1].to_string(),
"destination": keys[2].to_string(), "destination": keys[2].to_string(),
"authority": keys[0].to_string(), "authority": keys[0].to_string(),
"amount": 42, "amount": 42,
}) })
}
); );
let transfer_ix = transfer( let transfer_ix = transfer(
@ -445,14 +477,16 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "transfer", instruction_type: "transfer".to_string(),
info: json!({
"source": keys[2].to_string(), "source": keys[2].to_string(),
"destination": keys[3].to_string(), "destination": keys[3].to_string(),
"multisigAuthority": keys[4].to_string(), "multisigAuthority": keys[4].to_string(),
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(), "signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
"amount": 42, "amount": 42,
}) })
}
); );
// Test Approve, incl multisig // Test Approve, incl multisig
@ -469,13 +503,15 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "approve", instruction_type: "approve".to_string(),
info: json!({
"source": keys[1].to_string(), "source": keys[1].to_string(),
"delegate": keys[2].to_string(), "delegate": keys[2].to_string(),
"owner": keys[0].to_string(), "owner": keys[0].to_string(),
"amount": 42, "amount": 42,
}) })
}
); );
let approve_ix = approve( let approve_ix = approve(
@ -491,14 +527,16 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "approve", instruction_type: "approve".to_string(),
info: json!({
"source": keys[2].to_string(), "source": keys[2].to_string(),
"delegate": keys[3].to_string(), "delegate": keys[3].to_string(),
"multisigOwner": keys[4].to_string(), "multisigOwner": keys[4].to_string(),
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(), "signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
"amount": 42, "amount": 42,
}) })
}
); );
// Test Revoke // Test Revoke
@ -513,11 +551,13 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "revoke", instruction_type: "revoke".to_string(),
info: json!({
"source": keys[1].to_string(), "source": keys[1].to_string(),
"owner": keys[0].to_string(), "owner": keys[0].to_string(),
}) })
}
); );
// Test SetOwner // Test SetOwner
@ -533,12 +573,14 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "setOwner", instruction_type: "setOwner".to_string(),
info: json!({
"owned": keys[1].to_string(), "owned": keys[1].to_string(),
"newOwner": keys[2].to_string(), "newOwner": keys[2].to_string(),
"owner": keys[0].to_string(), "owner": keys[0].to_string(),
}) })
}
); );
// Test MintTo // Test MintTo
@ -555,13 +597,15 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "mintTo", instruction_type: "mintTo".to_string(),
info: json!({
"mint": keys[1].to_string(), "mint": keys[1].to_string(),
"account": keys[2].to_string(), "account": keys[2].to_string(),
"owner": keys[0].to_string(), "owner": keys[0].to_string(),
"amount": 42, "amount": 42,
}) })
}
); );
// Test Burn // Test Burn
@ -577,12 +621,14 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "burn", instruction_type: "burn".to_string(),
info: json!({
"account": keys[1].to_string(), "account": keys[1].to_string(),
"authority": keys[0].to_string(), "authority": keys[0].to_string(),
"amount": 42, "amount": 42,
}) })
}
); );
// Test CloseAccount // Test CloseAccount
@ -598,12 +644,14 @@ mod test {
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]); let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
assert_eq!( assert_eq!(
parse_token(&compiled_instruction, &keys).unwrap(), parse_token(&compiled_instruction, &keys).unwrap(),
json!({ ParsedInstructionEnum {
"type": "closeAccount", instruction_type: "closeAccount".to_string(),
info: json!({
"account": keys[1].to_string(), "account": keys[1].to_string(),
"destination": keys[2].to_string(), "destination": keys[2].to_string(),
"owner": keys[0].to_string(), "owner": keys[0].to_string(),
}) })
}
); );
} }