Update instruction encoding format (#11363)
* Rework parsed instruction format * Rework parsed message accounts * Review comments
This commit is contained in:
parent
86e3f96f16
commit
9d4f9be1fe
|
@ -7,8 +7,10 @@ pub mod parse_accounts;
|
|||
pub mod parse_instruction;
|
||||
pub mod parse_token;
|
||||
|
||||
use crate::{parse_accounts::parse_accounts, parse_instruction::parse};
|
||||
use serde_json::{json, Value};
|
||||
use crate::{
|
||||
parse_accounts::{parse_accounts, ParsedAccount},
|
||||
parse_instruction::{parse, ParsedInstruction},
|
||||
};
|
||||
use solana_sdk::{
|
||||
clock::{Slot, UnixTimestamp},
|
||||
commitment_config::CommitmentConfig,
|
||||
|
@ -23,7 +25,14 @@ use solana_sdk::{
|
|||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub enum UiInstruction {
|
||||
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
|
||||
|
@ -183,7 +192,7 @@ pub struct UiRawMessage {
|
|||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UiParsedMessage {
|
||||
pub account_keys: Value,
|
||||
pub account_keys: Vec<ParsedAccount>,
|
||||
pub recent_blockhash: String,
|
||||
pub instructions: Vec<UiInstruction>,
|
||||
}
|
||||
|
@ -250,13 +259,15 @@ impl EncodedTransaction {
|
|||
instruction,
|
||||
&transaction.message.account_keys,
|
||||
) {
|
||||
UiInstruction::Parsed(parsed_instruction)
|
||||
UiInstruction::Parsed(UiParsedInstruction::Parsed(
|
||||
parsed_instruction,
|
||||
))
|
||||
} else {
|
||||
UiInstruction::Parsed(json!(
|
||||
UiInstruction::Parsed(UiParsedInstruction::PartiallyDecoded(
|
||||
UiPartiallyDecodedInstruction::from(
|
||||
instruction,
|
||||
&transaction.message.account_keys
|
||||
)
|
||||
&transaction.message.account_keys,
|
||||
),
|
||||
))
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
use serde_json::{json, Map, Value};
|
||||
use solana_sdk::message::Message;
|
||||
|
||||
type AccountAttributes = Vec<AccountAttribute>;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
enum AccountAttribute {
|
||||
Signer,
|
||||
Writable,
|
||||
pub struct ParsedAccount {
|
||||
pub pubkey: String,
|
||||
pub writable: bool,
|
||||
pub signer: bool,
|
||||
}
|
||||
|
||||
pub fn parse_accounts(message: &Message) -> Value {
|
||||
let mut accounts: Map<String, Value> = Map::new();
|
||||
pub fn parse_accounts(message: &Message) -> Vec<ParsedAccount> {
|
||||
let mut accounts: Vec<ParsedAccount> = vec![];
|
||||
for (i, account_key) in message.account_keys.iter().enumerate() {
|
||||
let mut attributes: AccountAttributes = vec![];
|
||||
if message.is_writable(i) {
|
||||
attributes.push(AccountAttribute::Writable);
|
||||
}
|
||||
if message.is_signer(i) {
|
||||
attributes.push(AccountAttribute::Signer);
|
||||
}
|
||||
accounts.insert(account_key.to_string(), json!(attributes));
|
||||
accounts.push(ParsedAccount {
|
||||
pubkey: account_key.to_string(),
|
||||
writable: message.is_writable(i),
|
||||
signer: message.is_signer(i),
|
||||
});
|
||||
}
|
||||
json!(accounts)
|
||||
accounts
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -44,13 +39,30 @@ 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(): [],
|
||||
});
|
||||
|
||||
assert_eq!(parse_accounts(&message), expected_json);
|
||||
assert_eq!(
|
||||
parse_accounts(&message),
|
||||
vec![
|
||||
ParsedAccount {
|
||||
pubkey: pubkey0.to_string(),
|
||||
writable: true,
|
||||
signer: true,
|
||||
},
|
||||
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,
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::parse_token::parse_token;
|
||||
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_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
|
||||
use std::{
|
||||
|
@ -21,7 +21,7 @@ lazy_static! {
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ParseInstructionError {
|
||||
#[error("{0:?} instruction not parsable")]
|
||||
InstructionNotParsable(ParsableProgram),
|
||||
|
@ -31,6 +31,25 @@ pub enum ParseInstructionError {
|
|||
|
||||
#[error("Program not parsable")]
|
||||
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)]
|
||||
|
@ -44,17 +63,19 @@ pub fn parse(
|
|||
program_id: &Pubkey,
|
||||
instruction: &CompiledInstruction,
|
||||
account_keys: &[Pubkey],
|
||||
) -> Result<Value, ParseInstructionError> {
|
||||
) -> Result<ParsedInstruction, ParseInstructionError> {
|
||||
let program_name = PARSABLE_PROGRAM_IDS
|
||||
.get(program_id)
|
||||
.ok_or_else(|| ParseInstructionError::ProgramNotParsable)?;
|
||||
let parsed_json = match program_name {
|
||||
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!({
|
||||
format!("{:?}", program_name).to_kebab_case(): parsed_json
|
||||
}))
|
||||
Ok(ParsedInstruction {
|
||||
program: format!("{:?}", program_name).to_kebab_case(),
|
||||
program_id: program_id.to_string(),
|
||||
parsed: parsed_json,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_memo(instruction: &CompiledInstruction) -> Value {
|
||||
|
@ -64,6 +85,7 @@ fn parse_memo(instruction: &CompiledInstruction) -> Value {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
|
@ -72,18 +94,16 @@ mod test {
|
|||
accounts: vec![],
|
||||
data: vec![240, 159, 166, 150],
|
||||
};
|
||||
let expected_json = json!({
|
||||
"spl-memo": "🦖"
|
||||
});
|
||||
assert_eq!(
|
||||
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]);
|
||||
assert_eq!(
|
||||
parse(&non_parsable_program_id, &memo_instruction, &[]).unwrap_err(),
|
||||
ParseInstructionError::ProgramNotParsable
|
||||
);
|
||||
assert!(parse(&non_parsable_program_id, &memo_instruction, &[]).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::parse_instruction::{ParsableProgram, ParseInstructionError};
|
||||
use crate::parse_instruction::{ParsableProgram, ParseInstructionError, ParsedInstructionEnum};
|
||||
use serde_json::{json, Map, Value};
|
||||
use solana_sdk::{instruction::CompiledInstruction, pubkey::Pubkey};
|
||||
use spl_token_v1_0::instruction::TokenInstruction;
|
||||
|
@ -6,7 +6,7 @@ use spl_token_v1_0::instruction::TokenInstruction;
|
|||
pub fn parse_token(
|
||||
instruction: &CompiledInstruction,
|
||||
account_keys: &[Pubkey],
|
||||
) -> Result<Value, ParseInstructionError> {
|
||||
) -> Result<ParsedInstructionEnum, ParseInstructionError> {
|
||||
let token_instruction = TokenInstruction::unpack(&instruction.data)
|
||||
.map_err(|_| ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken))?;
|
||||
if instruction.accounts.len() > account_keys.len() {
|
||||
|
@ -23,7 +23,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "initializeMint",
|
||||
"mint": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"amount": amount,
|
||||
"decimals":decimals,
|
||||
|
@ -46,7 +45,10 @@ pub fn parse_token(
|
|||
);
|
||||
}
|
||||
}
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "initializeMint".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::InitializeAccount => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -54,12 +56,14 @@ pub fn parse_token(
|
|||
ParsableProgram::SplToken,
|
||||
));
|
||||
}
|
||||
Ok(json!({
|
||||
"type": "initializeAccount",
|
||||
"account": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"mint": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
"owner": account_keys[instruction.accounts[2] as usize].to_string(),
|
||||
}))
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "initializeAccount".to_string(),
|
||||
info: json!({
|
||||
"account": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"mint": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
"owner": account_keys[instruction.accounts[2] as usize].to_string(),
|
||||
}),
|
||||
})
|
||||
}
|
||||
TokenInstruction::InitializeMultisig { m } => {
|
||||
if instruction.accounts.len() < 2 {
|
||||
|
@ -71,12 +75,14 @@ pub fn parse_token(
|
|||
for i in instruction.accounts[1..].iter() {
|
||||
signers.push(account_keys[*i as usize].to_string());
|
||||
}
|
||||
Ok(json!({
|
||||
"type": "initializeMultisig",
|
||||
"multisig": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"signers": signers,
|
||||
"m": m,
|
||||
}))
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "initializeMultisig".to_string(),
|
||||
info: json!({
|
||||
"multisig": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"signers": signers,
|
||||
"m": m,
|
||||
}),
|
||||
})
|
||||
}
|
||||
TokenInstruction::Transfer { amount } => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -85,7 +91,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "transfer",
|
||||
"source": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"destination": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
"amount": amount,
|
||||
|
@ -99,7 +104,10 @@ pub fn parse_token(
|
|||
"authority",
|
||||
"multisigAuthority",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "transfer".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::Approve { amount } => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -108,7 +116,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "approve",
|
||||
"source": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"delegate": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
"amount": amount,
|
||||
|
@ -122,7 +129,10 @@ pub fn parse_token(
|
|||
"owner",
|
||||
"multisigOwner",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "approve".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::Revoke => {
|
||||
if instruction.accounts.len() < 2 {
|
||||
|
@ -131,7 +141,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "revoke",
|
||||
"source": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
});
|
||||
let mut map = value.as_object_mut().unwrap();
|
||||
|
@ -143,7 +152,10 @@ pub fn parse_token(
|
|||
"owner",
|
||||
"multisigOwner",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "revoke".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::SetOwner => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -152,7 +164,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "setOwner",
|
||||
"owned": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"newOwner": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
});
|
||||
|
@ -165,7 +176,10 @@ pub fn parse_token(
|
|||
"owner",
|
||||
"multisigOwner",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "setOwner".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::MintTo { amount } => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -174,7 +188,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "mintTo",
|
||||
"mint": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"account": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
"amount": amount,
|
||||
|
@ -188,7 +201,10 @@ pub fn parse_token(
|
|||
"owner",
|
||||
"multisigOwner",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "mintTo".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::Burn { amount } => {
|
||||
if instruction.accounts.len() < 2 {
|
||||
|
@ -197,7 +213,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "burn",
|
||||
"account": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"amount": amount,
|
||||
});
|
||||
|
@ -210,7 +225,10 @@ pub fn parse_token(
|
|||
"authority",
|
||||
"multisigAuthority",
|
||||
);
|
||||
Ok(value)
|
||||
Ok(ParsedInstructionEnum {
|
||||
instruction_type: "burn".to_string(),
|
||||
info: value,
|
||||
})
|
||||
}
|
||||
TokenInstruction::CloseAccount => {
|
||||
if instruction.accounts.len() < 3 {
|
||||
|
@ -219,7 +237,6 @@ pub fn parse_token(
|
|||
));
|
||||
}
|
||||
let mut value = json!({
|
||||
"type": "closeAccount",
|
||||
"account": account_keys[instruction.accounts[0] as usize].to_string(),
|
||||
"destination": account_keys[instruction.accounts[1] as usize].to_string(),
|
||||
});
|
||||
|
@ -232,7 +249,10 @@ pub fn parse_token(
|
|||
"owner",
|
||||
"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]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "initializeMint",
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
"decimals": 2,
|
||||
"account": keys[1].to_string(),
|
||||
"owner": keys[2].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "initializeMint".to_string(),
|
||||
info: json!({
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
"decimals": 2,
|
||||
"account": keys[1].to_string(),
|
||||
"owner": keys[2].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
let initialize_mint_ix = initialize_mint(
|
||||
|
@ -334,13 +356,15 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "initializeMint",
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
"decimals": 2,
|
||||
"account": keys[1].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "initializeMint".to_string(),
|
||||
info: json!({
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
"decimals": 2,
|
||||
"account": keys[1].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
let initialize_mint_ix = initialize_mint(
|
||||
|
@ -356,13 +380,15 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "initializeMint",
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 0,
|
||||
"decimals": 2,
|
||||
"owner": keys[1].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "initializeMint".to_string(),
|
||||
info: json!({
|
||||
"mint": keys[0].to_string(),
|
||||
"amount": 0,
|
||||
"decimals": 2,
|
||||
"owner": keys[1].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test InitializeAccount
|
||||
|
@ -377,12 +403,14 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "initializeAccount",
|
||||
"account": keys[0].to_string(),
|
||||
"mint": keys[1].to_string(),
|
||||
"owner": keys[2].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "initializeAccount".to_string(),
|
||||
info: json!({
|
||||
"account": keys[0].to_string(),
|
||||
"mint": keys[1].to_string(),
|
||||
"owner": keys[2].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test InitializeMultisig
|
||||
|
@ -401,12 +429,14 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "initializeMultisig",
|
||||
"multisig": keys[0].to_string(),
|
||||
"m": 2,
|
||||
"signers": keys[1..4].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "initializeMultisig".to_string(),
|
||||
info: json!({
|
||||
"multisig": keys[0].to_string(),
|
||||
"m": 2,
|
||||
"signers": keys[1..4].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test Transfer, incl multisig
|
||||
|
@ -423,13 +453,15 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "transfer",
|
||||
"source": keys[1].to_string(),
|
||||
"destination": keys[2].to_string(),
|
||||
"authority": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "transfer".to_string(),
|
||||
info: json!({
|
||||
"source": keys[1].to_string(),
|
||||
"destination": keys[2].to_string(),
|
||||
"authority": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
let transfer_ix = transfer(
|
||||
|
@ -445,14 +477,16 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "transfer",
|
||||
"source": keys[2].to_string(),
|
||||
"destination": keys[3].to_string(),
|
||||
"multisigAuthority": keys[4].to_string(),
|
||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "transfer".to_string(),
|
||||
info: json!({
|
||||
"source": keys[2].to_string(),
|
||||
"destination": keys[3].to_string(),
|
||||
"multisigAuthority": keys[4].to_string(),
|
||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test Approve, incl multisig
|
||||
|
@ -469,13 +503,15 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "approve",
|
||||
"source": keys[1].to_string(),
|
||||
"delegate": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "approve".to_string(),
|
||||
info: json!({
|
||||
"source": keys[1].to_string(),
|
||||
"delegate": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
let approve_ix = approve(
|
||||
|
@ -491,14 +527,16 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "approve",
|
||||
"source": keys[2].to_string(),
|
||||
"delegate": keys[3].to_string(),
|
||||
"multisigOwner": keys[4].to_string(),
|
||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "approve".to_string(),
|
||||
info: json!({
|
||||
"source": keys[2].to_string(),
|
||||
"delegate": keys[3].to_string(),
|
||||
"multisigOwner": keys[4].to_string(),
|
||||
"signers": keys[0..2].iter().map(|key| key.to_string()).collect::<Vec<String>>(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test Revoke
|
||||
|
@ -513,11 +551,13 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "revoke",
|
||||
"source": keys[1].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "revoke".to_string(),
|
||||
info: json!({
|
||||
"source": keys[1].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test SetOwner
|
||||
|
@ -533,12 +573,14 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "setOwner",
|
||||
"owned": keys[1].to_string(),
|
||||
"newOwner": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "setOwner".to_string(),
|
||||
info: json!({
|
||||
"owned": keys[1].to_string(),
|
||||
"newOwner": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test MintTo
|
||||
|
@ -555,13 +597,15 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "mintTo",
|
||||
"mint": keys[1].to_string(),
|
||||
"account": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "mintTo".to_string(),
|
||||
info: json!({
|
||||
"mint": keys[1].to_string(),
|
||||
"account": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test Burn
|
||||
|
@ -577,12 +621,14 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "burn",
|
||||
"account": keys[1].to_string(),
|
||||
"authority": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "burn".to_string(),
|
||||
info: json!({
|
||||
"account": keys[1].to_string(),
|
||||
"authority": keys[0].to_string(),
|
||||
"amount": 42,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
// Test CloseAccount
|
||||
|
@ -598,12 +644,14 @@ mod test {
|
|||
let compiled_instruction = convert_compiled_instruction(&message.instructions[0]);
|
||||
assert_eq!(
|
||||
parse_token(&compiled_instruction, &keys).unwrap(),
|
||||
json!({
|
||||
"type": "closeAccount",
|
||||
"account": keys[1].to_string(),
|
||||
"destination": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
ParsedInstructionEnum {
|
||||
instruction_type: "closeAccount".to_string(),
|
||||
info: json!({
|
||||
"account": keys[1].to_string(),
|
||||
"destination": keys[2].to_string(),
|
||||
"owner": keys[0].to_string(),
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue