bolt-cw-sdk 1.0.0

SDK for the BOLT protocol, providing utilities for interacting with the BOLT contracts.
Documentation
use super::test_scenario::TestScenario;
use crate::test_utils::helpers::{
    TEST_ASSET_ARCH_SYMBOL, TEST_ASSET_ETH_SYMBOL, TEST_ASSET_USDT_SYMBOL,
};
use crate::tx_builder::derivation_path::CosmosDerivationPath;
use crate::tx_builder::TxBuilder;
use bip32::Mnemonic;
use cosmrs::tendermint::abci::Code;
use cosmrs::AccountId;
use k256::elliptic_curve::rand_core::OsRng;

/// A collection of account related data required to send a message from it.
#[derive(Clone)]
pub struct TestAccount {
    pub mnemonic: String,
    pub account_id: AccountId,
}

impl TestAccount {
    pub fn new_random(
        chain_prefix: &str,
        chain_id: &str,
        derivation_path: CosmosDerivationPath,
    ) -> Self {
        let mnemonic = Mnemonic::random(OsRng, bip32::Language::English);

        let tx_builder = TxBuilder::new(
            mnemonic.phrase().to_string(),
            chain_prefix.to_string(),
            chain_id.to_string(),
            derivation_path,
            0,
            0,
        )
        .unwrap();

        let account_id = tx_builder.account_id;
        println!("New account created: {account_id}");

        Self {
            mnemonic: mnemonic.phrase().to_string(),
            account_id,
        }
    }
}

impl TestScenario {
    /// Creates a temporary account and sends to it initial funds from the admin.
    pub async fn create_new_account(&self) -> TestAccount {
        self.create_new_account_with_funds(10_000_000_000).await
    }

    pub async fn create_new_account_with_funds(&self, initial_funds: u128) -> TestAccount {
        let new_account =
            TestAccount::new_random(&self.chain_prefix, &self.chain_id, self.derivation_path);

        self.fund_account(&new_account, initial_funds).await;

        new_account
    }

    /// Send initial funds to the [TestAccount]
    pub async fn fund_account(&self, test_account: &TestAccount, initial_funds: u128) {
        let account = self
            .cosmos_client
            .account(self.admin_address.clone())
            .await
            .expect("Get account");
        let mut tx_builder = TxBuilder::new(
            self.admin_mnemonic.clone(),
            self.chain_prefix.clone(),
            self.chain_id.clone(),
            self.derivation_path,
            account.sequence,
            account.account_number,
        )
        .expect("Failed to create tx builder");

        // Create SendMsg
        const INITIAL_FEE_FUNDS: u128 = 1_000_000_000_000_000_000;
        let admin_account_id: AccountId = self
            .admin_address
            .parse()
            .expect("Should parse admin address to AccountId");

        self.add_send_msg(
            &mut tx_builder,
            admin_account_id.clone(),
            test_account.account_id.clone(),
            TEST_ASSET_ARCH_SYMBOL,
            initial_funds,
        );
        self.add_send_msg(
            &mut tx_builder,
            admin_account_id.clone(),
            test_account.account_id.clone(),
            TEST_ASSET_USDT_SYMBOL,
            initial_funds,
        );
        self.add_send_msg(
            &mut tx_builder,
            admin_account_id.clone(),
            test_account.account_id.clone(),
            TEST_ASSET_ETH_SYMBOL,
            initial_funds,
        );
        self.add_send_msg(
            &mut tx_builder,
            admin_account_id.clone(),
            test_account.account_id.clone(),
            &self.chain_denom,
            INITIAL_FEE_FUNDS,
        );

        tx_builder.set_memo("From create_new_account".to_string());
        let gas = 500_000u64;
        let amount = 20_000_000_000_000_000u128;
        tx_builder.set_fee(amount, &self.chain_denom, gas);
        let signed_bytes = tx_builder
            .get_signed_bytes()
            .expect("Failed to get signed bytes");
        let response = self
            .cosmos_client
            .broadcast_tx(signed_bytes)
            .await
            .expect("Failed to broadcast tx");
        if let Code::Err(code) = response.tx_result.code {
            panic!(
                "Transaction failed with code: {:?} response: {:?}",
                code, response
            );
        }
    }
}