whisky-csl 1.0.13

Wrapper around the cardano-serialization-lib for easier transaction building, heavily inspired by cardano-cli APIs
Documentation
use cardano_serialization_lib::{self as csl};
use hex::FromHex;
use whisky_common::*;

pub fn to_bignum(val: u64) -> Result<csl::BigNum, WError> {
    csl::BigNum::from_str(&val.to_string()).map_err(WError::from_err("to_bignum - invalid value"))
}

pub fn build_tx_builder(params: Option<Protocol>) -> Result<csl::TransactionBuilder, WError> {
    let protocol_params = params.unwrap_or_default();

    let cfg =
        csl::TransactionBuilderConfigBuilder::new()
            .fee_algo(&csl::LinearFee::new(
                &to_bignum(protocol_params.min_fee_a).map_err(WError::add_err_trace(
                    "build_tx_builder - invalid min fee a",
                ))?,
                &to_bignum(protocol_params.min_fee_b).map_err(WError::add_err_trace(
                    "build_tx_builder - invalid min fee b",
                ))?,
            ))
            .pool_deposit(&to_bignum(protocol_params.pool_deposit).map_err(
                WError::add_err_trace("build_tx_builder - invalid pool deposit"),
            )?)
            .key_deposit(
                &to_bignum(protocol_params.key_deposit).map_err(WError::add_err_trace(
                    "build_tx_builder - invalid key deposit",
                ))?,
            )
            .max_value_size(protocol_params.max_val_size)
            .max_tx_size(protocol_params.max_tx_size)
            .coins_per_utxo_byte(&to_bignum(protocol_params.coins_per_utxo_size).map_err(
                WError::add_err_trace("build_tx_builder - invalid coins per utxo byte"),
            )?)
            .ex_unit_prices(&csl::ExUnitPrices::new(
                &csl::UnitInterval::new(
                    &to_bignum((protocol_params.price_mem * 10000.0) as u64).map_err(
                        WError::add_err_trace("build_tx_builder - invalid price mem"),
                    )?,
                    &to_bignum(10000).unwrap(),
                ),
                &csl::UnitInterval::new(
                    &to_bignum((protocol_params.price_step * 10000000.0) as u64).map_err(
                        WError::add_err_trace("build_tx_builder - invalid price step"),
                    )?,
                    &to_bignum(10000000).unwrap(),
                ),
            ))
            .ref_script_coins_per_byte(&csl::UnitInterval::new(
                &to_bignum(protocol_params.min_fee_ref_script_cost_per_byte).map_err(
                    WError::add_err_trace(
                        "build_tx_builder - invalid min fee ref script cost per byte",
                    ),
                )?,
                &to_bignum(1).map_err(WError::add_err_trace(
                    "build_tx_builder - invalid min fee ref script cost per byte",
                ))?,
            ))
            .deduplicate_explicit_ref_inputs_with_regular_inputs(true)
            .build()
            .unwrap();
    Ok(csl::TransactionBuilder::new(&cfg))
}

pub fn to_value(assets: &Vec<Asset>) -> Result<csl::Value, WError> {
    let lovelace = assets.iter().find(|asset| asset.unit() == "lovelace");
    let mut multi_asset = csl::MultiAsset::new();

    for asset in assets {
        if asset.unit() == "lovelace" {
            continue;
        }
        let name_bytes = Vec::<u8>::from_hex(&asset.unit()[56..])
            .map_err(WError::from_err("to_value - invalid asset name hex"))?;
        multi_asset.set_asset(
            &csl::ScriptHash::from_hex(&asset.unit()[0..56])
                .map_err(WError::from_err("to_value - invalid asset script hash"))?,
            &csl::AssetName::new(name_bytes)
                .map_err(WError::from_err("to_value - invalid asset name hex"))?,
            &csl::BigNum::from_str(&asset.quantity().to_string())
                .map_err(WError::from_err("to_value - invalid asset quantity"))?,
        );
    }

    let lovelace_asset = match lovelace {
        Some(asset) => csl::BigNum::from_str(&asset.quantity()).map_err(WError::from_err(
            "to_value - invalid lovelace asset quantity",
        ))?,
        None => csl::BigNum::from_str("0").unwrap(),
    };

    let mut value = csl::Value::new(&lovelace_asset);

    if assets.len() > 1 || lovelace.is_none() {
        value.set_multiasset(&multi_asset);
    }
    Ok(value)
}