use {
crate::{SharedError, dataframe::DataFrame, node::Kind, utils::Buffer},
std::vec::Vec,
wincode::Deserialize,
};
use self::wincode_schema::VersionedTransactionSchema;
// type Transaction struct {
// Kind int
// Data DataFrame
// Metadata DataFrame
// Slot int
// Index **int
// }
/// Representation of a `Kind::Transaction` node containing the raw wire data.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Transaction {
/// Kind discriminator copied from the CBOR payload.
pub kind: u64,
/// Binary transaction payload stored as a [`DataFrame`].
pub data: DataFrame,
/// Associated metadata payload stored as a [`DataFrame`].
pub metadata: DataFrame,
/// Slot that produced the transaction.
pub slot: u64,
/// Optional within-slot transaction index.
pub index: Option<u64>,
}
impl Transaction {
/// Decodes a [`Transaction`] from raw CBOR bytes.
pub fn from_bytes(data: Vec<u8>) -> Result<Transaction, SharedError> {
let decoded_data: serde_cbor::Value = serde_cbor::from_slice(&data).unwrap();
let transaction = Transaction::from_cbor(decoded_data)?;
Ok(transaction)
}
/// Decodes a [`Transaction`] from a CBOR [`serde_cbor::Value`].
pub fn from_cbor(val: serde_cbor::Value) -> Result<Transaction, SharedError> {
let mut transaction = Transaction {
kind: 0,
data: DataFrame {
kind: 0,
hash: None,
index: None,
total: None,
data: Buffer::new(),
next: None,
},
metadata: DataFrame {
kind: 0,
hash: None,
index: None,
total: None,
data: Buffer::new(),
next: None,
},
slot: 0,
index: None,
};
if let serde_cbor::Value::Array(array) = val {
// println!("Kind: {:?}", array[0]);
if let Some(serde_cbor::Value::Integer(kind)) = array.first() {
// println!("Kind: {:?}", Kind::from_u64(kind as u64).unwrap().to_string());
transaction.kind = *kind as u64;
if *kind as u64 != Kind::Transaction as u64 {
return Err(Box::new(std::io::Error::other(std::format!(
"Wrong kind for Transaction; expected {:?}, got {:?}",
Kind::Transaction,
kind
))) as SharedError);
}
}
if let Some(serde_cbor::Value::Array(data)) = &array.get(1) {
transaction.data = DataFrame::from_cbor(serde_cbor::Value::Array(data.clone()))?;
}
if let Some(serde_cbor::Value::Array(metadata)) = &array.get(2) {
transaction.metadata =
DataFrame::from_cbor(serde_cbor::Value::Array(metadata.clone()))?;
}
if let Some(serde_cbor::Value::Integer(slot)) = array.get(3) {
transaction.slot = *slot as u64;
}
if let Some(serde_cbor::Value::Integer(index)) = array.get(4) {
transaction.index = Some(*index as u64);
}
}
Ok(transaction)
}
/// Renders the transaction as a JSON object for debugging.
pub fn to_json(&self) -> serde_json::Value {
let mut map = serde_json::Map::new();
map.insert("kind".to_string(), serde_json::Value::from(self.kind));
map.insert("data".to_string(), self.data.to_json());
map.insert("metadata".to_string(), self.metadata.to_json());
map.insert("slot".to_string(), serde_json::Value::from(self.slot));
map.insert("index".to_string(), serde_json::Value::from(self.index));
serde_json::Value::from(map)
}
/// Deserializes the transaction payload into a [`solana_transaction::versioned::VersionedTransaction`].
pub fn as_parsed(
&self,
) -> Result<solana_transaction::versioned::VersionedTransaction, SharedError> {
Ok(VersionedTransactionSchema::deserialize(
self.data.data.as_slice(),
)?)
}
/// Returns `true` when the transaction data frame has no continuation CIDs.
pub const fn is_complete_data(&self) -> bool {
self.data.next.is_none() || self.data.next.as_ref().unwrap().is_empty()
}
/// Returns `true` when the transaction metadata frame has no continuation CIDs.
pub const fn is_complete_metadata(&self) -> bool {
self.metadata.next.is_none() || self.metadata.next.as_ref().unwrap().is_empty()
}
}
mod wincode_schema {
use {
solana_address::Address,
solana_hash::Hash,
solana_message::{self, MESSAGE_VERSION_PREFIX, legacy, v0},
solana_signature::Signature,
solana_transaction::versioned,
std::mem::MaybeUninit,
wincode::{
ReadResult, SchemaRead, SchemaWrite, WriteResult,
containers::{self, Pod},
error::invalid_tag_encoding,
io::{Reader, Writer},
len::ShortU16Len,
},
};
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "solana_message::MessageHeader", struct_extensions)]
struct MessageHeader {
num_required_signatures: u8,
num_readonly_signed_accounts: u8,
num_readonly_unsigned_accounts: u8,
}
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "solana_message::compiled_instruction::CompiledInstruction")]
struct CompiledInstruction {
program_id_index: u8,
accounts: containers::Vec<Pod<u8>, ShortU16Len>,
data: containers::Vec<Pod<u8>, ShortU16Len>,
}
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "legacy::Message", struct_extensions)]
struct LegacyMessage {
header: MessageHeader,
account_keys: containers::Vec<Pod<Address>, ShortU16Len>,
recent_blockhash: Pod<Hash>,
instructions: containers::Vec<CompiledInstruction, ShortU16Len>,
}
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "v0::MessageAddressTableLookup")]
struct MessageAddressTableLookup {
account_key: Pod<Address>,
writable_indexes: containers::Vec<Pod<u8>, ShortU16Len>,
readonly_indexes: containers::Vec<Pod<u8>, ShortU16Len>,
}
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "v0::Message")]
struct V0Message {
#[wincode(with = "Pod<_>")]
header: solana_message::MessageHeader,
account_keys: containers::Vec<Pod<Address>, ShortU16Len>,
recent_blockhash: Pod<Hash>,
instructions: containers::Vec<CompiledInstruction, ShortU16Len>,
address_table_lookups: containers::Vec<MessageAddressTableLookup, ShortU16Len>,
}
#[derive(SchemaWrite, SchemaRead)]
#[wincode(from = "versioned::VersionedTransaction")]
pub(super) struct VersionedTransactionSchema {
signatures: containers::Vec<Pod<Signature>, ShortU16Len>,
message: VersionedMsg,
}
struct VersionedMsg;
impl SchemaWrite for VersionedMsg {
type Src = solana_message::VersionedMessage;
#[inline(always)]
fn size_of(src: &Self::Src) -> WriteResult<usize> {
match src {
solana_message::VersionedMessage::Legacy(message) => {
LegacyMessage::size_of(message)
}
// +1 for message version prefix
solana_message::VersionedMessage::V0(message) => {
Ok(1 + V0Message::size_of(message)?)
}
}
}
#[inline(always)]
fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
match src {
solana_message::VersionedMessage::Legacy(message) => {
LegacyMessage::write(writer, message)
}
solana_message::VersionedMessage::V0(message) => {
u8::write(writer, &MESSAGE_VERSION_PREFIX)?;
V0Message::write(writer, message)
}
}
}
}
impl<'de> SchemaRead<'de> for VersionedMsg {
type Dst = solana_message::VersionedMessage;
fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
let variant = u8::get(reader)?;
if variant & MESSAGE_VERSION_PREFIX != 0 {
let version = variant & !MESSAGE_VERSION_PREFIX;
return match version {
0 => {
let msg = V0Message::get(reader)?;
dst.write(solana_message::VersionedMessage::V0(msg));
Ok(())
}
_ => Err(invalid_tag_encoding(version as usize)),
};
}
let mut msg = MaybeUninit::<legacy::Message>::uninit();
let header_uninit = LegacyMessage::uninit_header_mut(&mut msg);
MessageHeader::write_uninit_num_required_signatures(variant, header_uninit);
MessageHeader::read_num_readonly_signed_accounts(reader, header_uninit)?;
MessageHeader::read_num_readonly_unsigned_accounts(reader, header_uninit)?;
LegacyMessage::read_account_keys(reader, &mut msg)?;
LegacyMessage::read_recent_blockhash(reader, &mut msg)?;
LegacyMessage::read_instructions(reader, &mut msg)?;
let msg = unsafe { msg.assume_init() };
dst.write(solana_message::VersionedMessage::Legacy(msg));
Ok(())
}
}
}
#[cfg(test)]
mod transaction_tests {
use {super::*, cid::Cid};
#[test]
fn test_transaction() {
let transaction = Transaction {
kind: 1,
data: DataFrame {
kind: 6,
hash: Some(1),
index: Some(1),
total: Some(1),
data: Buffer::from_vec(vec![1]),
next: Some(vec![
Cid::try_from(
vec![
1, 113, 18, 32, 56, 148, 167, 251, 237, 117, 200, 226, 181, 134, 79,
115, 131, 220, 232, 143, 20, 67, 224, 179, 48, 130, 197, 123, 226, 85,
85, 56, 38, 84, 106, 225,
]
.as_slice(),
)
.unwrap(),
]),
},
metadata: DataFrame {
kind: 6,
hash: Some(1),
index: Some(1),
total: Some(1),
data: Buffer::from_vec(vec![1]),
next: Some(vec![
Cid::try_from(
vec![
1, 113, 18, 32, 56, 148, 167, 251, 237, 117, 200, 226, 181, 134, 79,
115, 131, 220, 232, 143, 20, 67, 224, 179, 48, 130, 197, 123, 226, 85,
85, 56, 38, 84, 106, 225,
]
.as_slice(),
)
.unwrap(),
]),
},
slot: 1,
index: Some(1),
};
let json = transaction.to_json();
let wanted_json = serde_json::json!({
"kind": 1,
"data": {
"kind": 6,
"hash": "1",
"index": 1,
"total": 1,
"data": Buffer::from_vec(vec![1]).to_string(),
"next": [{
"/":"bafyreibysst7x3lvzdrllbspoob5z2epcrb6bmzqqlcxxysvku4cmvdk4e"
}]
},
"metadata": {
"kind": 6,
"hash": "1",
"index": 1,
"total": 1,
"data": Buffer::from_vec(vec![1]).to_string(),
"next": [{
"/":"bafyreibysst7x3lvzdrllbspoob5z2epcrb6bmzqqlcxxysvku4cmvdk4e"
}]
},
"slot": 1,
"index": 1
});
assert_eq!(json, wanted_json);
}
#[test]
fn test_decoding() {
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 74, 1, 134, 211, 49, 71, 74, 192, 231, 203,
60, 87, 178, 248, 12, 50, 114, 214, 129, 182, 44, 219, 155, 48, 56, 26, 34, 169,
31, 8, 254, 225, 154, 223, 40, 155, 190, 199, 41, 122, 237, 248, 217, 3, 163, 103,
212, 255, 27, 131, 158, 213, 220, 233, 238, 101, 89, 148, 91, 44, 124, 121, 34, 29,
19, 8, 1, 0, 3, 5, 5, 25, 184, 120, 214, 101, 64, 179, 24, 204, 134, 159, 34, 65,
196, 27, 118, 194, 159, 13, 31, 33, 150, 62, 102, 171, 127, 138, 217, 198, 46, 167,
5, 25, 184, 108, 163, 149, 211, 120, 201, 249, 2, 7, 70, 58, 37, 139, 66, 81, 204,
62, 85, 3, 238, 187, 182, 56, 109, 100, 146, 228, 35, 74, 6, 167, 213, 23, 25, 47,
10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41, 208, 190, 59,
19, 110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99,
152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0, 0,
0, 0, 7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211, 189, 179, 216,
53, 94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 182, 60, 207, 33, 158,
150, 214, 144, 149, 162, 94, 67, 156, 12, 11, 6, 76, 240, 19, 151, 216, 246, 121,
45, 88, 34, 202, 217, 240, 232, 241, 11, 1, 4, 4, 1, 2, 3, 0, 61, 2, 0, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0, 125, 20, 1, 1, 0, 0, 0, 0, 126, 20, 1, 1, 0, 0, 0, 0, 242, 171,
7, 179, 147, 12, 194, 246, 147, 38, 135, 62, 250, 65, 130, 82, 252, 134, 159, 218,
29, 218, 191, 18, 122, 23, 147, 40, 41, 53, 184, 88, 0, 133, 6, 246, 246, 246, 88,
59, 40, 181, 47, 253, 4, 0, 117, 1, 0, 34, 66, 7, 16, 208, 71, 1, 63, 61, 210, 40,
159, 253, 19, 122, 41, 43, 143, 242, 125, 96, 156, 189, 165, 133, 94, 14, 17, 234,
253, 193, 124, 5, 0, 167, 122, 8, 50, 94, 65, 214, 206, 28, 106, 40, 95, 237, 237,
196, 226, 26, 1, 1, 20, 132, 0,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AYbTMUdKwOfLPFey+AwyctaBtizbmzA4GiKpHwj+4ZrfKJu+xyl67fjZA6Nn1P8bg57V3OnuZVmUWyx8eSIdEwgBAAMFBRm4eNZlQLMYzIafIkHEG3bCnw0fIZY+Zqt/itnGLqcFGbhso5XTeMn5AgdGOiWLQlHMPlUD7ru2OG1kkuQjSgan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAALY8zyGeltaQlaJeQ5wMCwZM8BOX2PZ5LVgiytnw6PELAQQEAQIDAD0CAAAAAgAAAAAAAAB9FAEBAAAAAH4UAQEAAAAA8qsHs5MMwvaTJoc++kGCUvyGn9od2r8SeheTKCk1uFgA","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"KLUv/QQAdQEAIkIHENBHAT890iif/RN6KSuP8n1gnL2lhV4OEer9wXwFAKd6CDJeQdbOHGooX+3txOI=","next":null},"slot":16848004,"index":0});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 66, 1, 151, 159, 89, 187, 97, 25, 142, 3,
174, 85, 157, 116, 102, 197, 178, 214, 246, 74, 226, 141, 31, 105, 16, 37, 67, 105,
225, 141, 254, 92, 224, 101, 93, 67, 251, 238, 169, 227, 57, 40, 109, 130, 196,
111, 38, 164, 190, 143, 138, 201, 237, 155, 1, 79, 81, 30, 199, 180, 46, 87, 224,
244, 40, 10, 1, 0, 3, 5, 172, 22, 10, 112, 218, 101, 149, 13, 246, 88, 186, 12, 9,
221, 143, 104, 189, 65, 202, 38, 214, 139, 78, 84, 16, 83, 141, 70, 208, 142, 246,
211, 127, 174, 161, 97, 171, 234, 188, 35, 150, 54, 103, 237, 9, 22, 182, 119, 200,
88, 156, 56, 108, 149, 249, 232, 100, 47, 132, 163, 172, 119, 226, 37, 6, 167, 213,
23, 25, 47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41,
208, 190, 59, 19, 110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201,
40, 86, 99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85,
91, 33, 0, 0, 0, 0, 7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211,
189, 179, 216, 53, 94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 4, 201,
29, 212, 80, 118, 182, 160, 37, 251, 217, 53, 53, 233, 25, 246, 252, 227, 101, 151,
134, 14, 148, 250, 179, 200, 158, 39, 252, 116, 174, 37, 1, 4, 4, 1, 2, 3, 0, 53,
2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 127, 20, 1, 1, 0, 0, 0, 0, 34, 140, 235, 141,
252, 67, 143, 16, 185, 136, 66, 108, 201, 186, 4, 240, 250, 90, 51, 224, 222, 196,
82, 242, 30, 110, 233, 49, 110, 196, 49, 109, 0, 133, 6, 246, 246, 246, 88, 60, 40,
181, 47, 253, 4, 0, 125, 1, 0, 34, 130, 7, 17, 224, 73, 1, 128, 250, 173, 82, 174,
11, 170, 74, 29, 145, 65, 49, 190, 15, 10, 157, 189, 157, 100, 62, 2, 89, 226, 253,
160, 124, 5, 0, 167, 122, 8, 50, 94, 65, 214, 206, 28, 106, 40, 95, 16, 123, 220,
102, 26, 1, 1, 20, 132, 6,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AZefWbthGY4DrlWddGbFstb2SuKNH2kQJUNp4Y3+XOBlXUP77qnjOShtgsRvJqS+j4rJ7ZsBT1Eex7QuV+D0KAoBAAMFrBYKcNpllQ32WLoMCd2PaL1ByibWi05UEFONRtCO9tN/rqFhq+q8I5Y2Z+0JFrZ3yFicOGyV+ehkL4SjrHfiJQan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAATJHdRQdragJfvZNTXpGfb842WXhg6U+rPInif8dK4lAQQEAQIDADUCAAAAAQAAAAAAAAB/FAEBAAAAACKM6438Q48QuYhCbMm6BPD6WjPg3sRS8h5u6TFuxDFtAA==","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"KLUv/QQAfQEAIoIHEeBJAYD6rVKuC6pKHZFBMb4PCp29nWQ+Alni/aB8BQCneggyXkHWzhxqKF8Qe9xm","next":null},"slot":16848004,"index":6});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 74, 1, 77, 56, 38, 7, 194, 192, 28, 222, 51,
93, 37, 184, 107, 166, 11, 163, 39, 199, 194, 22, 136, 238, 106, 134, 241, 210,
230, 111, 82, 132, 58, 57, 182, 245, 103, 20, 212, 127, 136, 207, 86, 78, 145, 44,
95, 194, 150, 52, 180, 58, 22, 60, 38, 119, 51, 173, 193, 149, 101, 36, 50, 80, 53,
14, 1, 0, 3, 5, 190, 70, 100, 24, 253, 30, 159, 110, 80, 154, 11, 229, 134, 11, 97,
240, 128, 102, 162, 236, 119, 116, 81, 222, 200, 65, 22, 104, 192, 248, 4, 36, 238,
79, 232, 183, 174, 31, 1, 233, 191, 201, 171, 51, 122, 73, 184, 10, 99, 218, 1, 71,
77, 136, 192, 226, 244, 4, 5, 41, 165, 165, 43, 177, 6, 167, 213, 23, 25, 47, 10,
175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41, 208, 190, 59, 19,
110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99, 152,
105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0, 0, 0, 0,
7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211, 189, 179, 216, 53,
94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 182, 60, 207, 33, 158,
150, 214, 144, 149, 162, 94, 67, 156, 12, 11, 6, 76, 240, 19, 151, 216, 246, 121,
45, 88, 34, 202, 217, 240, 232, 241, 11, 1, 4, 4, 1, 2, 3, 0, 61, 2, 0, 0, 0, 2, 0,
0, 0, 0, 0, 0, 0, 125, 20, 1, 1, 0, 0, 0, 0, 126, 20, 1, 1, 0, 0, 0, 0, 242, 171,
7, 179, 147, 12, 194, 246, 147, 38, 135, 62, 250, 65, 130, 82, 252, 134, 159, 218,
29, 218, 191, 18, 122, 23, 147, 40, 41, 53, 184, 88, 0, 133, 6, 246, 246, 246, 88,
60, 40, 181, 47, 253, 4, 0, 125, 1, 0, 34, 130, 7, 17, 208, 71, 1, 15, 126, 161,
171, 215, 190, 136, 255, 30, 141, 212, 35, 124, 31, 104, 156, 189, 29, 101, 78,
130, 72, 235, 253, 160, 124, 5, 0, 167, 122, 8, 50, 94, 65, 214, 206, 28, 106, 40,
95, 22, 54, 11, 168, 26, 1, 1, 20, 132, 8,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AU04JgfCwBzeM10luGumC6Mnx8IWiO5qhvHS5m9ShDo5tvVnFNR/iM9WTpEsX8KWNLQ6FjwmdzOtwZVlJDJQNQ4BAAMFvkZkGP0en25Qmgvlhgth8IBmoux3dFHeyEEWaMD4BCTuT+i3rh8B6b/JqzN6SbgKY9oBR02IwOL0BAUppaUrsQan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAALY8zyGeltaQlaJeQ5wMCwZM8BOX2PZ5LVgiytnw6PELAQQEAQIDAD0CAAAAAgAAAAAAAAB9FAEBAAAAAH4UAQEAAAAA8qsHs5MMwvaTJoc++kGCUvyGn9od2r8SeheTKCk1uFgA","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"KLUv/QQAfQEAIoIHEdBHAQ9+oavXvoj/Ho3UI3wfaJy9HWVOgkjr/aB8BQCneggyXkHWzhxqKF8WNguo","next":null},"slot":16848004,"index":8});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 74, 1, 184, 225, 58, 101, 82, 111, 167, 65,
53, 254, 197, 113, 213, 145, 193, 123, 203, 12, 233, 149, 120, 43, 195, 116, 126,
44, 173, 8, 91, 41, 28, 35, 213, 132, 158, 203, 27, 161, 167, 40, 32, 77, 153, 112,
239, 76, 170, 93, 5, 252, 225, 83, 56, 16, 16, 186, 219, 240, 67, 87, 114, 170, 53,
0, 1, 0, 3, 5, 172, 22, 10, 112, 218, 101, 149, 13, 246, 88, 186, 12, 9, 221, 143,
104, 189, 65, 202, 38, 214, 139, 78, 84, 16, 83, 141, 70, 208, 142, 246, 211, 127,
174, 161, 97, 171, 234, 188, 35, 150, 54, 103, 237, 9, 22, 182, 119, 200, 88, 156,
56, 108, 149, 249, 232, 100, 47, 132, 163, 172, 119, 226, 37, 6, 167, 213, 23, 25,
47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41, 208, 190,
59, 19, 110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201, 40, 86,
99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0,
0, 0, 0, 7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211, 189, 179,
216, 53, 94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 57, 115, 227, 48,
194, 155, 131, 31, 63, 203, 14, 73, 55, 78, 216, 208, 56, 143, 65, 10, 35, 228,
235, 242, 51, 40, 80, 80, 54, 239, 189, 3, 1, 4, 4, 1, 2, 3, 0, 61, 2, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 3, 64, 92, 84, 205, 196, 47, 165,
30, 214, 130, 189, 56, 19, 137, 214, 2, 67, 245, 115, 151, 196, 222, 30, 118, 173,
83, 211, 213, 98, 74, 1, 155, 141, 111, 94, 0, 0, 0, 0, 133, 6, 246, 246, 246, 64,
1, 1,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AbjhOmVSb6dBNf7FcdWRwXvLDOmVeCvDdH4srQhbKRwj1YSeyxuhpyggTZlw70yqXQX84VM4EBC62/BDV3KqNQABAAMFrBYKcNpllQ32WLoMCd2PaL1ByibWi05UEFONRtCO9tN/rqFhq+q8I5Y2Z+0JFrZ3yFicOGyV+ehkL4SjrHfiJQan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAADlz4zDCm4MfP8sOSTdO2NA4j0EKI+Tr8jMoUFA2770DAQQEAQIDAD0CAAAAAQAAAAAAAAAAAAAAAAAAAKsDQFxUzcQvpR7Wgr04E4nWAkP1c5fE3h52rVPT1WJKAZuNb14AAAAA","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"","next":null},"slot":1,"index":1});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 74, 1, 209, 218, 80, 205, 183, 226, 44, 58,
188, 80, 169, 129, 20, 90, 23, 130, 239, 173, 189, 172, 2, 98, 168, 145, 31, 193,
131, 54, 144, 44, 133, 91, 197, 203, 77, 135, 52, 132, 228, 140, 123, 66, 190, 138,
193, 104, 202, 136, 198, 60, 159, 228, 136, 161, 97, 79, 183, 181, 202, 219, 184,
16, 210, 2, 1, 0, 3, 5, 8, 174, 144, 179, 253, 128, 62, 129, 35, 232, 153, 1, 56,
61, 76, 245, 77, 47, 140, 172, 72, 99, 201, 10, 175, 163, 76, 80, 69, 184, 105,
195, 8, 174, 144, 179, 221, 8, 189, 75, 88, 135, 173, 62, 74, 163, 208, 136, 15,
182, 90, 121, 92, 255, 108, 230, 47, 143, 61, 249, 76, 92, 69, 116, 6, 167, 213,
23, 25, 47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41,
208, 190, 59, 19, 110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201,
40, 86, 99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85,
91, 33, 0, 0, 0, 0, 7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211,
189, 179, 216, 53, 94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 182,
60, 207, 33, 158, 150, 214, 144, 149, 162, 94, 67, 156, 12, 11, 6, 76, 240, 19,
151, 216, 246, 121, 45, 88, 34, 202, 217, 240, 232, 241, 11, 1, 4, 4, 1, 2, 3, 0,
61, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 125, 20, 1, 1, 0, 0, 0, 0, 126, 20, 1, 1,
0, 0, 0, 0, 242, 171, 7, 179, 147, 12, 194, 246, 147, 38, 135, 62, 250, 65, 130,
82, 252, 134, 159, 218, 29, 218, 191, 18, 122, 23, 147, 40, 41, 53, 184, 88, 0,
133, 6, 246, 246, 246, 88, 59, 40, 181, 47, 253, 4, 0, 117, 1, 0, 34, 66, 7, 16,
224, 73, 1, 0, 168, 9, 24, 157, 82, 90, 181, 218, 67, 81, 191, 15, 2, 88, 125, 157,
116, 39, 200, 140, 107, 127, 40, 31, 5, 0, 167, 122, 8, 50, 94, 65, 214, 206, 28,
106, 40, 95, 143, 10, 67, 190, 26, 1, 1, 20, 132, 1,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AdHaUM234iw6vFCpgRRaF4Lvrb2sAmKokR/BgzaQLIVbxctNhzSE5Ix7Qr6KwWjKiMY8n+SIoWFPt7XK27gQ0gIBAAMFCK6Qs/2APoEj6JkBOD1M9U0vjKxIY8kKr6NMUEW4acMIrpCz3Qi9S1iHrT5Ko9CID7ZaeVz/bOYvjz35TFxFdAan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAALY8zyGeltaQlaJeQ5wMCwZM8BOX2PZ5LVgiytnw6PELAQQEAQIDAD0CAAAAAgAAAAAAAAB9FAEBAAAAAH4UAQEAAAAA8qsHs5MMwvaTJoc++kGCUvyGn9od2r8SeheTKCk1uFgA","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"KLUv/QQAdQEAIkIHEOBJAQCoCRidUlq12kNRvw8CWH2ddCfIjGt/KB8FAKd6CDJeQdbOHGooX48KQ74=","next":null},"slot":16848004,"index":1});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
{
let raw = vec![
133, 0, 133, 6, 246, 246, 246, 89, 1, 82, 1, 7, 129, 215, 180, 55, 12, 107, 0, 191,
100, 122, 6, 102, 204, 238, 233, 26, 95, 38, 50, 157, 117, 102, 175, 231, 40, 105,
159, 211, 41, 252, 138, 221, 248, 201, 176, 68, 46, 213, 242, 96, 239, 1, 13, 247,
199, 59, 15, 227, 127, 42, 144, 68, 138, 39, 148, 186, 108, 159, 69, 202, 35, 166,
2, 1, 0, 3, 5, 25, 186, 124, 248, 30, 85, 38, 82, 76, 137, 213, 19, 241, 20, 187,
124, 55, 101, 45, 215, 64, 18, 62, 67, 242, 195, 34, 238, 13, 131, 155, 166, 178,
221, 184, 16, 109, 186, 103, 212, 50, 177, 183, 25, 134, 20, 39, 250, 37, 111, 219,
217, 104, 215, 137, 162, 222, 110, 196, 196, 148, 168, 35, 45, 6, 167, 213, 23, 25,
47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41, 208, 190,
59, 19, 110, 45, 0, 85, 32, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201, 40, 86,
99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0,
0, 0, 0, 7, 97, 72, 29, 53, 116, 116, 187, 124, 77, 118, 36, 235, 211, 189, 179,
216, 53, 94, 115, 209, 16, 67, 252, 13, 163, 83, 128, 0, 0, 0, 0, 4, 201, 29, 212,
80, 118, 182, 160, 37, 251, 217, 53, 53, 233, 25, 246, 252, 227, 101, 151, 134, 14,
148, 250, 179, 200, 158, 39, 252, 116, 174, 37, 1, 4, 4, 1, 2, 3, 0, 69, 2, 0, 0,
0, 3, 0, 0, 0, 0, 0, 0, 0, 125, 20, 1, 1, 0, 0, 0, 0, 126, 20, 1, 1, 0, 0, 0, 0,
127, 20, 1, 1, 0, 0, 0, 0, 34, 140, 235, 141, 252, 67, 143, 16, 185, 136, 66, 108,
201, 186, 4, 240, 250, 90, 51, 224, 222, 196, 82, 242, 30, 110, 233, 49, 110, 196,
49, 109, 0, 133, 6, 246, 246, 246, 88, 59, 40, 181, 47, 253, 4, 0, 117, 1, 0, 34,
66, 7, 16, 224, 73, 1, 56, 247, 104, 106, 157, 235, 62, 6, 214, 24, 10, 249, 125,
129, 88, 125, 153, 83, 62, 14, 137, 212, 126, 112, 31, 5, 0, 167, 122, 8, 50, 94,
65, 214, 206, 28, 106, 40, 95, 20, 171, 252, 8, 26, 1, 1, 20, 132, 4,
];
let as_json_raw = serde_json::json!({"kind":0,"data":{"kind":6,"hash":null,"index":null,"total":null,"data":"AQeB17Q3DGsAv2R6BmbM7ukaXyYynXVmr+coaZ/TKfyK3fjJsEQu1fJg7wEN98c7D+N/KpBEiieUumyfRcojpgIBAAMFGbp8+B5VJlJMidUT8RS7fDdlLddAEj5D8sMi7g2Dm6ay3bgQbbpn1DKxtxmGFCf6JW/b2WjXiaLebsTElKgjLQan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAATJHdRQdragJfvZNTXpGfb842WXhg6U+rPInif8dK4lAQQEAQIDAEUCAAAAAwAAAAAAAAB9FAEBAAAAAH4UAQEAAAAAfxQBAQAAAAAijOuN/EOPELmIQmzJugTw+loz4N7EUvIebukxbsQxbQA=","next":null},"metadata":{"kind":6,"hash":null,"index":null,"total":null,"data":"KLUv/QQAdQEAIkIHEOBJATj3aGqd6z4G1hgK+X2BWH2ZUz4OidR+cB8FAKd6CDJeQdbOHGooXxSr/Ag=","next":null},"slot":16848004,"index":4});
let transaction = Transaction::from_bytes(raw).unwrap();
let as_json = transaction.to_json();
assert_eq!(as_json, as_json_raw);
}
}
}