diff --git a/Cargo.toml b/Cargo.toml index 39e9fc0..5d55ae4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ edition = "2021" reqwest = { version = "0.11.4", features = ["json"] } url = "2.2.2" tokio = { version = "1.15.0", features = ["full"] } -xdr-codec = "0.4.4" -xdrgen = "0.4.4" +stellar-xdr = { version = "0.0.17", features = ["base64"] } [build-dependencies] \ No newline at end of file diff --git a/src/horizon_client/horizon_client.rs b/src/horizon_client/horizon_client.rs index 5d722c6..cf73fa6 100644 --- a/src/horizon_client/horizon_client.rs +++ b/src/horizon_client/horizon_client.rs @@ -86,7 +86,7 @@ async fn handle_response( println!("Response: {:?}", response); match response.status() { reqwest::StatusCode::OK => { - let response = response.text().await.map_err(|e| e.to_string())?; + let _response = response.text().await.map_err(|e| e.to_string())?; Ok(TResponse::default()) //decode(&response.as_bytes()).map_err(|e| e.to_string()); // match result { @@ -112,8 +112,6 @@ fn url_validate(url: &str) -> Result<(), String> { #[cfg(test)] mod tests { - use crate::horizon_client; - use super::*; #[test] @@ -163,7 +161,9 @@ mod tests { single_account_request .set_account_id("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7".to_string()); - let _single_account_response = horizon_client.get_single_account(&single_account_request).await; + let _single_account_response = horizon_client + .get_single_account(&single_account_request) + .await; assert!(_single_account_response.is_ok()); } diff --git a/src/lib.rs b/src/lib.rs index b6d95ad..6b70aa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,3 @@ mod accounts; mod horizon_client; mod models; mod xdr; - diff --git a/src/xdr/mod.rs b/src/xdr/mod.rs index 8c73fa8..b750904 100644 --- a/src/xdr/mod.rs +++ b/src/xdr/mod.rs @@ -1,49 +1,8 @@ -use xdr_codec; - -use self::stub_data::LedgerHeader; - -/// Encodes a value to XDR. -/// # Arguments -/// * `value` - The value to encode -/// # Returns -/// The encoded value -/// # Errors -/// Returns an error if the encoding fails -pub fn encode(value: &T) -> Result { - todo!(); -} - -/// decodes a value from XDR. -/// # Arguments -/// * `bytes` - The bytes to decode -/// # Returns -/// The decoded value -/// # Errors -/// Returns an error if the decoding fails -/// # Remarks -pub fn decode(mut bytes: &[u8]) -> Result -where - T: Default, -{ - println!("bytes: {:?}", bytes); - let xdr: Result = xdr_codec::unpack(&mut bytes); - match xdr { - Ok(v) => Ok(v), - Err(e) => { - Err(e.to_string()) - }, - } -} - #[cfg(test)] mod tests { - use super::*; - use stub_data::*; - #[test] - fn encode_ledger_header() { - let ledger_header = ""; - } + use ::stellar_xdr::ReadXdr; + use stellar_xdr::curr as stellar_xdr; // TODO, add vice versa. // https://developers.stellar.org/docs/encyclopedia/xdr#parsing-xdr @@ -53,247 +12,57 @@ mod tests { fn decode_ledger_header() { // Decode online at : https://stellar.github.io/xdr-viewer/?type=LedgerHeader&network=public let encoded = "AAAAAGPZj1Nu5o0bJ7W4nyOvUxG3Vpok+vFAOtC1K2M7B76ZuZRHr9UdXKbTKiclfOjy72YZFJUkJPVcKT5htvorm1QAAAAAZImGNAAAAAAAAAABAAAAAKgkzRi8nXUGTSmaW1uspDvDqi8yaTgVPYwvm7XLbfAzAAAAQLuRQK8ocAjytwfQelkpwZQa5+jReIO0pbr/9BbUbIffRxQN4Z76J3qDIn5lSJpn0OkYL8ZLPGP0W/S1vlTj5w/fP2GYBKkv20BXGS3EPddI6neK3FK8SYzoBSTAFLgRGXNSJ+05hGEpEjdoewhEaqLJsJbgyYpGLa3aVp8F3SSEAAAAAg3gtrOnZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkBfXhAAAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".as_bytes(); - - let decoded = decode::(&encoded).unwrap(); - assert_eq!(decoded.ledger_version, 0); - assert_eq!(decoded.previous_ledger_hash, "Y9mPU27mjRsntbifI69TEbdWmiT68UA60LUrYzsHvpk=".to_string()); - assert_eq!(decoded.tx_set_hash, "uZRHr9UdXKbTKiclfOjy72YZFJUkJPVcKT5htvorm1Q=".to_string()); - assert_eq!(decoded.close_time, 1686734388); - - // let decoded = decode::(&encoded).unwrap(); - // assert_eq!(decoded, LedgerHeader::default()); - // assert_eq!(decoded.ledger_version, 0); - // assert_eq!( - // decoded.previous_ledger_hash, - // "7KhW4Ac9wghySdySntMcCcO6v+8uaHtoXQUT2+ZImhg=" - // ); - // assert_eq!(decoded.scp_value, ""); - // assert_eq!( - // decoded.tx_set_hash, - // "jqmROBaaGtCUsskwAA+EA0DXG49VbiW3E/OP5gIanTc=" - // ); - // assert_eq!(decoded.close_time, 1686734395); - // assert_eq!(decoded.upgrades.len(), 0); - // assert_eq!(decoded.ext, vec!["stellarValueSigned"]); - // assert_eq!(decoded.lc_value_signature, ""); - // assert_eq!(decoded.node_id, vec!["publicKeyTypeEd25519"]); - // assert_eq!( - // decoded.ed25519, - // "7KhW4Ac9wghySdySntMcCcO6v+8uaHtoXQUT2+ZImhg=" - // ); - // assert_eq!( - // decoded.signature, - // "jqmROBaaGtCUsskwAA+EA0DXG49VbiW3E/OP5gIanTc=" - // ); - // assert_eq!( - // decoded.tx_set_result_hash, - // "jqmROBaaGtCUsskwAA+EA0DXG49VbiW3E/OP5gIanTc=" - // ); - // assert_eq!( - // decoded.bucket_list_hash, - // "jqmROBaaGtCUsskwAA+EA0DXG49VbiW3E/OP5gIanTc=" - // ); - // assert_eq!(decoded.ledger_seq, 3); - // assert_eq!(decoded.total_coins, 1000000000000000000); - // assert_eq!(decoded.fee_pool, 0); - // assert_eq!(decoded.inflation_seq, 0); - // assert_eq!(decoded.id_pool, 0); - // assert_eq!(decoded.base_fee, 100); - // assert_eq!(decoded.base_reserve, 100000000); - // assert_eq!(decoded.max_tx_set_size, 100); - // // assert_eq!(decoded.skip_list, vec![ - // // "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", - // // "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", - // // "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", - // // "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="]); - } -} - -mod stub_data { - use xdr_codec::Unpack; - - #[derive(Debug)] - pub struct LedgerHeader { - pub ledger_version: i32, - pub previous_ledger_hash: String, - pub scp_value: String, - pub tx_set_hash: String, - pub close_time: i64, - pub upgrades: Vec, - pub ext: Vec, - pub lc_value_signature: String, - pub node_id: Vec, - pub ed25519: String, - pub signature: String, - pub tx_set_result_hash: String, - pub bucket_list_hash: String, - pub ledger_seq: i32, - pub total_coins: i64, - pub fee_pool: i64, - pub inflation_seq: i32, - pub id_pool: i64, - pub base_fee: i32, - pub base_reserve: i64, - pub max_tx_set_size: i32, - pub skip_list: Vec, - } - - impl PartialEq for LedgerHeader { - fn eq(&self, other: &Self) -> bool { - true - } - } + let decoded = stellar_xdr::LedgerHeader::from_xdr_base64(encoded).unwrap(); + println!("Decoded: {:?}", decoded); + assert_eq!(decoded.ledger_version, 0); + assert_eq!( + decoded.previous_ledger_hash.to_string(), + "63d98f536ee68d1b27b5b89f23af5311b7569a24faf1403ad0b52b633b07be99" + ); + assert_eq!(decoded.scp_value.upgrades.len(), 0); + assert_eq!( + decoded.scp_value.tx_set_hash.to_string(), + "b99447afd51d5ca6d32a27257ce8f2ef661914952424f55c293e61b6fa2b9b54" + ); + assert_eq!(decoded.scp_value.close_time.0, 1686734388); + assert_eq!( + decoded.tx_set_result_hash.to_string(), + "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119" + ); - impl Unpack<&[u8]> for LedgerHeader { - fn unpack(input: &mut &[u8]) -> xdr_codec::Result<(Self, usize)> { - let mut size = 0; - let ledger_header = LedgerHeader { - ledger_version: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - print!("ledger_version: {:?}\n", v); - v - }, - previous_ledger_hash: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - scp_value: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - tx_set_hash: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - close_time: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - upgrades: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - ext: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - lc_value_signature: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - node_id: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - ed25519: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - signature: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - tx_set_result_hash: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - bucket_list_hash: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - ledger_seq: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - total_coins: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - fee_pool: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - inflation_seq: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - id_pool: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - base_fee: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - base_reserve: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - max_tx_set_size: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - skip_list: { - let (v, sz) = Unpack::unpack(input)?; - size += sz; - v - }, - }; - - println!("-------------LEDGER HEADER: {:?}", ledger_header); - Ok((ledger_header, size)) + match decoded.scp_value.ext { + ::stellar_xdr::StellarValueExt::Signed(signed) => { + assert_eq!( + signed.node_id.0.discriminant().to_string(), + "PublicKeyTypeEd25519" + ); + assert_eq!(signed.node_id.0.name().to_string(), "PublicKeyTypeEd25519"); + // todo check node-id public key + // todo check signature + } + _ => panic!("Expected signed"), } - } - impl Default for LedgerHeader { - fn default() -> Self { - Self { - ledger_version: 0, - previous_ledger_hash: "".to_string(), - scp_value: "".to_string(), - tx_set_hash: "".to_string(), - close_time: 0, - upgrades: vec![], - ext: vec![], - lc_value_signature: "".to_string(), - node_id: vec![], - ed25519: "".to_string(), - signature: "".to_string(), - tx_set_result_hash: "".to_string(), - bucket_list_hash: "".to_string(), - ledger_seq: 0, - total_coins: 0, - fee_pool: 0, - inflation_seq: 0, - id_pool: 0, - base_fee: 0, - base_reserve: 0, - max_tx_set_size: 0, - skip_list: vec![], - } + assert_eq!( + decoded.bucket_list_hash.to_string(), + "735227ed398461291237687b08446aa2c9b096e0c98a462dadda569f05dd2484" + ); + assert_eq!(decoded.ledger_seq, 2); + assert_eq!(decoded.total_coins, 1000000000000000000); + assert_eq!(decoded.fee_pool, 0); + assert_eq!(decoded.inflation_seq, 0); + assert_eq!(decoded.id_pool, 0); + assert_eq!(decoded.base_fee, 100); + assert_eq!(decoded.base_reserve, 100000000); + assert_eq!(decoded.max_tx_set_size, 100); + assert_eq!(decoded.ext, stellar_xdr::LedgerHeaderExt::V0); + for decoded in decoded.skip_list { + assert_eq!( + decoded.to_string(), + "0000000000000000000000000000000000000000000000000000000000000000" + ); } } }