Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- add read for data transaction #2

Merged
merged 1 commit into from
Aug 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ blake2 = "0.10.4"
sha3 = "0.10.2"
sha2 = "0.10.2"
curve25519-dalek = "3.2.1"
base64 = "0.13.0"

reqwest = { version = "0.11.11", features = ["json"] }
tokio = { version = "1.12.0", features = ["full"] }
Expand Down
12 changes: 9 additions & 3 deletions src/json_deserializer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::model::TransactionData::Transfer;
use crate::model::TransactionData::{Data, Transfer};
use crate::model::{
ApplicationStatus, SignedTransaction, Transaction, TransactionInfo, TransferTransaction,
ApplicationStatus, DataTransaction, SignedTransaction, Transaction, TransactionInfo,
TransferTransaction,
};
use serde_json::Value;

Expand Down Expand Up @@ -32,7 +33,12 @@ pub fn from_json(value: Value) -> TransactionInfo {
};
let height = value["height"].as_i64().unwrap() as u32;

let transaction_data = Transfer(TransferTransaction::from_json(value));
let transaction_data = match tx_type {
4 => Transfer(TransferTransaction::from_json(value)),
12 => Data(DataTransaction::from_json(value)),
_ => panic!("unknown tx type"),
};

let transaction = Transaction::new(
transaction_data,
fee,
Expand Down
40 changes: 40 additions & 0 deletions src/model/data_entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::model::data_entry::DataEntry::{
BinaryEntry, BooleanEntry, DeleteEntry, IntegerEntry, StringEntry,
};
use serde_json::Value;

#[derive(Clone)]
pub enum DataEntry {
IntegerEntry { key: String, value: u64 },
BooleanEntry { key: String, value: bool },
BinaryEntry { key: String, value: Vec<u8> },
StringEntry { key: String, value: String },
DeleteEntry { key: String },
}

impl From<&Value> for DataEntry {
fn from(value: &Value) -> Self {
let key_field = value["key"].as_str().unwrap().into();
let value_field = &value["value"];
match value["type"].as_str().unwrap() {
"" => DeleteEntry { key: key_field },
"binary" => BinaryEntry {
key: key_field,
value: base64::decode(value_field.as_str().unwrap()).unwrap(),
},
"boolean" => BooleanEntry {
key: key_field,
value: value_field.as_bool().unwrap(),
},
"integer" => IntegerEntry {
key: key_field,
value: value_field.as_u64().unwrap(),
},
"string" => StringEntry {
key: key_field,
value: value_field.as_str().unwrap().into(),
},
_ => panic!("unknown type"),
}
}
}
1 change: 1 addition & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod account;
pub mod asset;
pub mod base58string;
pub mod chain_id;
pub mod data_entry;
pub mod transaction;

pub use asset::*;
Expand Down
24 changes: 24 additions & 0 deletions src/model/transaction/data_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::model::data_entry::DataEntry;
use serde_json::Value;

pub struct DataTransaction {
data: Vec<DataEntry>,
}

impl DataTransaction {
// todo return Result<DataTransaction, Error>
pub fn from_json(value: Value) -> DataTransaction {
let data = value["data"]
.as_array()
.unwrap()
.iter()
.map(|entry| entry.into())
.collect::<Vec<DataEntry>>();

DataTransaction { data }
}

pub fn data(&self) -> Vec<DataEntry> {
self.data.clone()
}
}
2 changes: 2 additions & 0 deletions src/model/transaction/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod data_transaction;
mod transaction_info;
mod transfer_transaction;

pub use data_transaction::*;
pub use transaction_info::*;
pub use transfer_transaction::*;
12 changes: 11 additions & 1 deletion src/model/transaction/transaction_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::model::account::PublicKey;
use crate::model::transaction::data_transaction::DataTransaction;
use crate::model::transaction::TransactionData::Transfer;
use crate::model::transaction::TransferTransaction;
use crate::model::TransactionData::Data;

pub struct TransactionInfo {
id: String,
Expand Down Expand Up @@ -110,16 +112,24 @@ impl Transaction {

pub enum TransactionData {
Transfer(TransferTransaction),
Data(DataTransaction),
Issue(),
}

impl TransactionData {
pub fn transfer(&self) -> Result<&TransferTransaction, String> {
pub fn transfer_tx(&self) -> Result<&TransferTransaction, String> {
match self {
Transfer(tx) => Ok(tx),
_ => Err("failed".into()),
}
}

pub fn data_tx(&self) -> Result<&DataTransaction, String> {
match self {
Data(tx) => Ok(tx),
_ => Err("failed".into()),
}
}
}

pub struct SignedTransaction {
Expand Down
61 changes: 59 additions & 2 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ impl Profile {
mod tests {
use ChainId::MAINNET;

use crate::model::data_entry::DataEntry;
use crate::model::{ApplicationStatus, ChainId};
use crate::node::{Node, Profile};

#[tokio::test]
async fn test_get_transaction_info() {
async fn test_get_transfer_transaction_info() {
let tx_id = "8YsBZSZ3UmWAo8bCj8RN64BvoQUTdLtd567hXqQCYDVo";

let node = Node::from_profile(Profile::MAINNET);
Expand Down Expand Up @@ -125,7 +126,7 @@ mod tests {
assert_eq!(transaction.tx_type(), 4);
assert_eq!(transaction.version(), 1);

let transfer_transaction = transaction.data().transfer().unwrap();
let transfer_transaction = transaction.data().transfer_tx().unwrap();
assert_eq!(transfer_transaction.attachment(), Some("".into()));
assert_eq!(
transfer_transaction.recipient(),
Expand All @@ -134,4 +135,60 @@ mod tests {
assert_eq!(transfer_transaction.asset(), None);
assert_eq!(transfer_transaction.amount(), 46095972);
}

#[tokio::test]
async fn test_get_data_transaction_info() {
let tx_id = "HcPcSma7oWeqy8g3ahhwFDzrq8YK8r739U4WC2ieB5Bs";

let node = Node::from_profile(Profile::MAINNET);
let transaction_info = node.get_transaction_info(tx_id.into()).await;

assert_eq!(
transaction_info.id(),
"HcPcSma7oWeqy8g3ahhwFDzrq8YK8r739U4WC2ieB5Bs"
);
assert_eq!(transaction_info.status(), ApplicationStatus::Succeed);
assert_eq!(transaction_info.height(), 3258212);

let signed_transaction = transaction_info.signed_tx();

let proof_from_rs = "25KiXB1FS3FaupiPXyEVeRquKLK4FEb3NWF36D1eHw1gpT9Y53MbLsVqnX9rJC8MPg4x9yiUxFkmxF9DDTgQruhi";
assert_eq!(signed_transaction.proofs()[0], proof_from_rs.as_bytes());

let transaction = signed_transaction.tx();

assert_eq!(transaction.timestamp(), 1660994483097);
assert_eq!(transaction.fee(), 500000);
assert_eq!(transaction.fee_asset_id(), None);
assert_eq!(
transaction.public_key().address(MAINNET.byte()).encoded(),
"3P4sxdNNPJLQcitAnLqLfSwaenjxFxQvZsE"
);
assert_eq!(
transaction.public_key().encoded(),
"GTr2dXt3mxaD8tXGyNauV8YMy1hsSoi63DUuk4uyijqG"
);
assert_eq!(transaction.tx_type(), 12);
assert_eq!(transaction.version(), 1);

let data_transaction = transaction.data().data_tx().unwrap();

let data_entries = data_transaction.data();

match data_entries[0].clone() {
DataEntry::IntegerEntry { key, value } => {
assert_eq!(key, "price_ausdtlpm_20220820");
assert_eq!(value, 1823153 as u64)
}
_ => panic!("failed"),
};

match data_entries[1].clone() {
DataEntry::IntegerEntry { key, value } => {
assert_eq!(key, "lastHeight_ausdtlpm");
assert_eq!(value, 3258212 as u64)
}
_ => panic!("failed"),
}
}
}