use super::{amount::Amount, deserialize};
use chrono::prelude::*;
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "lowercase", tag = "memo_type", content = "memo")]
pub enum Memo {
Text(String),
Id(i64),
Hash(String),
Return(String),
None,
}
#[derive(Deserialize, Debug, Clone)]
pub struct Transaction {
id: String,
paging_token: String,
hash: String,
ledger: u32,
created_at: DateTime<Utc>,
source_account: String,
#[serde(deserialize_with = "deserialize::from_str")]
source_account_sequence: u64,
fee_paid: i64,
operation_count: u32,
envelope_xdr: String,
result_xdr: String,
result_meta_xdr: String,
fee_meta_xdr: String,
#[serde(flatten)]
memo: Memo,
}
impl Transaction {
pub fn id(&self) -> &String {
&self.id
}
pub fn paging_token(&self) -> &String {
&self.paging_token
}
pub fn hash(&self) -> &String {
&self.hash
}
pub fn ledger(&self) -> u32 {
self.ledger
}
pub fn created_at(&self) -> DateTime<Utc> {
self.created_at
}
pub fn source_account(&self) -> &String {
&self.source_account
}
pub fn source_account_sequence(&self) -> u64 {
self.source_account_sequence
}
pub fn fee_paid(&self) -> i64 {
self.fee_paid
}
pub fn fee_as_amount(&self) -> Amount {
Amount::new(self.fee_paid)
}
pub fn operation_count(&self) -> u32 {
self.operation_count
}
pub fn envelope_xdr(&self) -> &String {
&self.envelope_xdr
}
pub fn result_xdr(&self) -> &String {
&self.result_xdr
}
pub fn result_meta_xdr(&self) -> &String {
&self.result_meta_xdr
}
pub fn fee_meta_xdr(&self) -> &String {
&self.fee_meta_xdr
}
pub fn memo(&self) -> &Memo {
&self.memo
}
}
#[cfg(test)]
mod transaction_tests {
use super::*;
use serde_json;
fn transaction_json() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_text.json")
}
fn transaction_json_memo_text() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_text.json")
}
fn transaction_json_memo_hash() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_hash.json")
}
fn transaction_json_memo_id() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_id.json")
}
fn transaction_json_memo_return() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_return.json")
}
fn transaction_json_memo_none() -> &'static str {
include_str!("../../fixtures/transactions/transaction_memo_none.json")
}
#[test]
fn it_parses_into_a_transaction() {
let transaction: Transaction = serde_json::from_str(&transaction_json()).unwrap();
assert_eq!(
transaction.id(),
"648da0d47aa3b3b20afd4499a68f89b6d10ead8b1f38858e99b1d94b6fef6e69"
);
assert_eq!(transaction.paging_token(), "71946212651044864");
assert_eq!(
transaction.hash(),
"648da0d47aa3b3b20afd4499a68f89b6d10ead8b1f38858e99b1d94b6fef6e69"
);
assert_eq!(transaction.ledger(), 16751283);
assert_eq!(
transaction.created_at(),
Utc.ymd(2018, 3, 10).and_hms(23, 16, 42)
);
assert_eq!(
transaction.source_account(),
"GB6YPGW5JFMMP2QB2USQ33EUWTXVL4ZT5ITUNCY3YKVWOJPP57CANOF3"
);
assert_eq!(transaction.source_account_sequence(), 2394452857640034);
assert_eq!(transaction.fee_paid(), 100);
assert_eq!(transaction.fee_as_amount(), Amount::new(100));
assert_eq!(transaction.operation_count(), 1);
assert_eq!(
transaction.envelope_xdr(),
"AAAAAH2Hmt1JWMfqAdUlDeyUtO9V8zPqJ0aLG8KrZyXv78QGAAAAZAAIgb4AAtRiAAAAAAAAAAEAAAAAAAAA\
AQAAAAAAAAABAAAAAJZgy/0KAk+3JQwG8hPGBNTZVGew2Joi1TwkVBdwPn9QAAAAAAAAAAA7mUNgAAAAAAAAA\
AHv78QGAAAAQITCXzWfgHgAjF3djx1VK9JK08UypfpftzFoyNXv7A0Agau/ur/3/+ZZtQb8xSsao8yVAsTiV4\
ttiT/HqfvvlAk="
);
assert_eq!(
transaction.result_xdr(),
"AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAA="
);
assert_eq!(
transaction.result_meta_xdr(),
"AAAAAAAAAAEAAAAEAAAAAwD/mrMAAAAAAAAAAH2Hmt1JWMfqAdUlDeyUtO9V8zPqJ0aLG8KrZyXv78QGACqz0\
JcAUz4ACIG+AALUYgAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAQD/mrMAAAAAAAAAAH2Hmt1\
JWMfqAdUlDeyUtO9V8zPqJ0aLG8KrZyXv78QGACqz0FtnD94ACIG+AALUYgAAAAAAAAAAAAAAAAAAAAABAAAAA\
AAAAAAAAAAAAAAAAAAAAwD45pUAAAAAAAAAAJZgy/0KAk+3JQwG8hPGBNTZVGew2Joi1TwkVBdwPn9QAAAAAAD\
ccSUA7xgIAAAAAQAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAQD/mrMAAAAAAAAAAJZgy/0KA\
k+3JQwG8hPGBNTZVGew2Joi1TwkVBdwPn9QAAAAADx1tIUA7xgIAAAAAQAAAAAAAAAAAAAAAAAAAAABAAAAAAA\
AAAAAAAAAAAAA"
);
assert_eq!(
transaction.fee_meta_xdr(),
"AAAAAgAAAAMA/5qyAAAAAAAAAAB9h5rdSVjH6gHVJQ3slLTvVfMz6idGixvCq2cl7+/EBgAqs9CXAFOiAAiBv\
gAC1GEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAEA/5qzAAAAAAAAAAB9h5rdSVjH6gHVJQ3\
slLTvVfMz6idGixvCq2cl7+/EBgAqs9CXAFM+AAiBvgAC1GIAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAA\
AAAAA=="
);
if let &Memo::Text(ref value) = transaction.memo() {
assert_eq!(value, "hello");
} else {
panic!("Can't parse memo text.");
}
}
#[test]
fn it_parses_memo_text() {
let transaction: Transaction = serde_json::from_str(&transaction_json_memo_text()).unwrap();
if let &Memo::Text(ref value) = transaction.memo() {
assert_eq!(value, "hello");
} else {
panic!("Can't parse memo tesxt.");
}
}
#[test]
fn it_parses_memo_hash() {
let transaction: Transaction = serde_json::from_str(&transaction_json_memo_hash()).unwrap();
if let &Memo::Hash(ref value) = transaction.memo() {
assert_eq!(
value,
"2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824"
);
} else {
panic!("Can't parse memo hash.");
}
}
#[test]
fn it_parses_memo_id() {
let transaction: Transaction = serde_json::from_str(&transaction_json_memo_id()).unwrap();
if let &Memo::Id(value) = transaction.memo() {
assert_eq!(value, 19292920);
} else {
panic!("Can't parse memo id.");
}
}
#[test]
fn it_parses_memo_return() {
let transaction: Transaction =
serde_json::from_str(&transaction_json_memo_return()).unwrap();
if let &Memo::Return(ref value) = transaction.memo() {
assert_eq!(
value,
"2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824"
);
} else {
panic!("Can't parse memo return.");
}
}
#[test]
fn it_parses_memo_none() {
let transaction: Transaction = serde_json::from_str(&transaction_json_memo_none()).unwrap();
assert_eq!(transaction.memo(), &Memo::None);
}
}