soroban-cli 26.0.0

Soroban CLI
Documentation
use stellar_xdr::curr::MuxedAccount;

use crate::{
    commands::{
        global,
        tx::xdr::{tx_envelope_from_input, Error as XdrParsingError},
    },
    config::{self, locator, network},
    xdr::{self, SequenceNumber, TransactionEnvelope, WriteXdr},
};

#[derive(clap::Parser, Debug, Clone)]
pub struct Cmd {
    #[command(flatten)]
    pub network: network::Args,
    #[command(flatten)]
    pub locator: locator::Args,
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error(transparent)]
    XdrStdin(#[from] XdrParsingError),
    #[error(transparent)]
    Xdr(#[from] xdr::Error),
    #[error("V0 and fee bump transactions are not supported")]
    Unsupported,
    #[error(transparent)]
    RpcClient(#[from] crate::rpc::Error),
    #[error(transparent)]
    Config(#[from] config::Error),
    #[error(transparent)]
    Network(#[from] config::network::Error),
}

impl Cmd {
    pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
        let mut tx = tx_envelope_from_input(&None)?;
        self.update_tx_env(&mut tx, global_args).await?;
        println!("{}", tx.to_xdr_base64(xdr::Limits::none())?);
        Ok(())
    }

    pub async fn update_tx_env(
        &self,
        tx_env: &mut TransactionEnvelope,
        _global: &global::Args,
    ) -> Result<(), Error> {
        match tx_env {
            TransactionEnvelope::Tx(transaction_v1_envelope) => {
                let tx_source_acct = &transaction_v1_envelope.tx.source_account;
                let current_seq_num = self.current_seq_num(tx_source_acct).await?;
                let next_seq_num = current_seq_num + 1;
                transaction_v1_envelope.tx.seq_num = SequenceNumber(next_seq_num);
            }
            TransactionEnvelope::TxV0(_) | TransactionEnvelope::TxFeeBump(_) => {
                return Err(Error::Unsupported);
            }
        }
        Ok(())
    }

    async fn current_seq_num(&self, tx_source_acct: &MuxedAccount) -> Result<i64, Error> {
        let network = &self.network.get(&self.locator)?;
        let client = network.rpc_client()?;
        client
            .verify_network_passphrase(Some(&network.network_passphrase))
            .await?;

        let address = tx_source_acct.to_string();

        let account = client.get_account(&address).await?;
        Ok(*account.seq_num.as_ref())
    }
}