substrate-stellar-sdk 0.3.0

A Substrate compatible SDK for Stellar
Documentation
use crate::{
    compound_types::UnlimitedVarArray,
    lib::{FromUtf8Error, String},
    types::{GeneralizedTransactionSet, TransactionPhase, TxSetComponent},
    Hash, IntoHash, StellarSdkError, TransactionEnvelope, XdrCodec,
};

impl IntoHash for GeneralizedTransactionSet {
    fn into_hash(self) -> Result<Hash, StellarSdkError> {
        use sha2::{Digest, Sha256};
        use sp_std::convert::TryInto;

        let mut hasher = Sha256::new();
        hasher.update(self.to_xdr());

        hasher
            .finalize()
            .as_slice()
            .try_into()
            .map_err(|_| StellarSdkError::InvalidHashConversion)
    }
}

impl GeneralizedTransactionSet {
    pub fn to_base64_encoded_xdr_string(&self) -> Result<String, FromUtf8Error> {
        let base_64 = self.clone().to_base64_xdr();
        String::from_utf8(base_64)
    }

    pub fn previous_ledger_hash(&self) -> Option<Hash> {
        let GeneralizedTransactionSet::V1(txset_v1) = self else {
            return None;
        };
        Some(txset_v1.previous_ledger_hash)
    }

    pub fn txes(&self) -> Option<UnlimitedVarArray<TransactionEnvelope>> {
        let GeneralizedTransactionSet::V1(txset_v1) = self else {
            return None;
        };

        let mut final_txes = UnlimitedVarArray::new_empty();

        for phase in txset_v1.phases.get_vec() {
            let TransactionPhase::V0(txsets_comp) = phase else {
                return None;
            };

            for TxSetComponent::TxsetCompTxsMaybeDiscountedFee(discounted_txs_set) in txsets_comp.get_vec() {
                if final_txes.len() == 0 {
                    final_txes = discounted_txs_set.txes.clone();
                } else {
                    for tx in discounted_txs_set.txes.get_vec() {
                        if let Err(_) = final_txes.push(tx.clone()) {
                            return None
                        }
                    }
                }
            }
        }

        Some(final_txes)
    }
}

#[cfg(test)]
mod tests {
    use crate::{types::GeneralizedTransactionSet, Hash, XdrCodec};

    const GENERALIZED_TX_SET: &str = "AAAAAVUcNbdctOS+OftZngTJY07YUUqb4P1I/owUmgdMuzscAAAAAgAAAAAAAAABAAAAAAAAAAEAAAAAAAAAZAAAAAEAAAACAAAAAMgOELhl9VFf5x0pG1aY8Mm/QQcnigdQ9MgWM1F8c6HSAAAAZAAZMt8AADrRAAAAAQAAAAAAAAAAAAAAAGUb2+8AAAABAAAAG3RzOjIwMjMtMTAtMDNUMDk6MTU6MDEuNTkyWgAAAAABAAAAAAAAAAEAAAAAf4MDV2AZH1oB1nouL9LSGUHGGafzcb48GXQyWFd9zswAAAAAAAAAAACYloAAAAAAAAAAAXxzodIAAABAEq3w/8HQ6kjqooVJPjg1TquL2pMOT+P9P7a3HpdqUYyFyJ8F32igbhIu3jvIJkafhDTosuL/rid2BxmScxhfDwAAAAAAAAAA";

    fn example() -> GeneralizedTransactionSet {
        let to_vec_u8 = GENERALIZED_TX_SET.as_bytes().to_vec();
        GeneralizedTransactionSet::from_base64_xdr(to_vec_u8).expect("should return a GeneralizedTransactionSet")
    }

    #[test]
    fn generalized_transaction_set_to_string() {
        let gen_txset_as_str = example()
            .to_base64_encoded_xdr_string()
            .expect("should be able to convert to string.");

        assert_eq!(gen_txset_as_str, GENERALIZED_TX_SET);
    }

    #[test]
    fn generalized_transaction_set_returns_prev_ledger_hash() {
        let expected_hash = "VRw1t1y05L45+1meBMljTthRSpvg/Uj+jBSaB0y7Oxw=".as_bytes();
        let expected_hash = Hash::from_base64_xdr(expected_hash).expect("return hash");

        let gen_tx_set = example();
        let actual_hash = gen_tx_set.previous_ledger_hash().expect("should return a previous ledger hash");

        assert_eq!(actual_hash, expected_hash);
    }

    #[test]
    fn generalized_transaction_set_returns_txset() {
        let gen_tx_set = example();
        let txes = gen_tx_set.txes().expect("should return an array of tx envelopes");

        assert!(!txes.get_vec().is_empty());
    }
}