use crate::{
address,
assets::Assets,
constants::{
CPU_COST_DENOMINATOR, CPU_COST_NUMERATOR, Config, MAINNET_COLLATERAL_UTXO,
MEM_COST_DENOMINATOR, MEM_COST_NUMERATOR, OVERHEAD_COST, PREPROD_COLLATERAL_UTXO,
UTXO_COST_PER_BYTE, get_config,
},
register::Register,
schnorr,
};
use pallas_addresses::Address;
use pallas_crypto::hash::Hash;
use pallas_primitives::Fragment;
use pallas_txbuilder::{Input, Output};
use serde_json::Value;
pub fn calculate_min_required_utxo(output: Output) -> u64 {
let output_cbor_length: u64 = output
.build_babbage_raw()
.unwrap()
.encode_fragment()
.unwrap()
.len()
.try_into()
.unwrap();
(OVERHEAD_COST + output_cbor_length) * UTXO_COST_PER_BYTE
}
pub fn collateral_input(network_flag: bool) -> Input {
let utxo: &str = if network_flag {
PREPROD_COLLATERAL_UTXO
} else {
MAINNET_COLLATERAL_UTXO
};
Input::new(
pallas_crypto::hash::Hash::new(
hex::decode(utxo)
.expect("Invalid hex string")
.try_into()
.expect("Failed to convert to 32-byte array"),
),
0,
)
}
pub fn seedelf_reference_utxo(network_flag: bool, variant: u64) -> Input {
let config: Config = get_config(variant, network_flag).unwrap_or_else(|| {
eprintln!("Error: Invalid Variant");
std::process::exit(1);
});
Input::new(
Hash::new(
hex::decode(config.reference.seedelf_reference_utxo)
.expect("Invalid hex string")
.try_into()
.expect("Failed to convert to 32-byte array"),
),
1,
)
}
pub fn wallet_reference_utxo(network_flag: bool, variant: u64) -> Input {
let config: Config = get_config(variant, network_flag).unwrap_or_else(|| {
eprintln!("Error: Invalid Variant");
std::process::exit(1);
});
Input::new(
Hash::new(
hex::decode(config.reference.wallet_reference_utxo)
.expect("Invalid hex string")
.try_into()
.expect("Failed to convert to 32-byte array"),
),
1,
)
}
pub fn seedelf_token_name(label: String, inputs: Option<&Vec<Input>>) -> Vec<u8> {
let mut label_hex: String = hex::encode(label);
label_hex.truncate(30);
let smallest_input: &Input = inputs
.and_then(|inputs| {
inputs.iter().min_by(|a, b| {
a.tx_hash
.0
.cmp(&b.tx_hash.0)
.then(a.txo_index.cmp(&b.txo_index))
})
})
.unwrap();
let formatted_index: String = format!("{:02x}", smallest_input.txo_index);
let tx_hash_hex: String = hex::encode(smallest_input.tx_hash.0);
let prefix: String = "5eed0e1f".to_string();
let concatenated: String = format!("{}{}{}{}", prefix, label_hex, formatted_index, tx_hash_hex);
hex::decode(&concatenated[..64.min(concatenated.len())]).unwrap()
}
pub fn computation_fee(mem_units: u64, cpu_units: u64) -> u64 {
(MEM_COST_NUMERATOR * mem_units / MEM_COST_DENOMINATOR)
+ (CPU_COST_NUMERATOR * cpu_units / CPU_COST_DENOMINATOR)
}
pub fn extract_budgets(value: &Value) -> Vec<(u64, u64)> {
let mut budgets: Vec<(u64, u64)> = Vec::new();
if let Some(result_array) = value.get("result").and_then(|r| r.as_array()) {
for item in result_array {
if let Some(budget) = item.get("budget") {
if let (Some(cpu), Some(memory)) = (
budget.get("cpu").and_then(|c| c.as_u64()),
budget.get("memory").and_then(|m| m.as_u64()),
) {
budgets.push((cpu, memory));
}
}
}
}
budgets
}
pub fn total_computation_fee(budgets: Vec<(u64, u64)>) -> u64 {
let mut fee: u64 = 0;
for (cpu, mem) in budgets.into_iter() {
fee += computation_fee(mem, cpu);
}
fee
}
pub fn seedelf_minimum_lovelace() -> u64 {
let token_name: Vec<u8> = [
94, 237, 14, 31, 1, 66, 250, 134, 20, 230, 198, 12, 121, 19, 73, 107, 154, 156, 226, 154,
138, 103, 76, 134, 93, 156, 23, 169, 169, 167, 201, 55,
]
.to_vec();
let policy_id: Vec<u8> = [
94, 237, 14, 31, 1, 66, 250, 134, 20, 230, 198, 12, 121, 19, 73, 107, 154, 156, 226, 154,
138, 103, 76, 134, 93, 156, 23, 169,
]
.to_vec();
let staging_output: Output = Output::new(address::wallet_contract(true, 1), 5_000_000)
.set_inline_datum(
Register::create(schnorr::random_scalar())
.rerandomize()
.to_vec(),
)
.add_asset(
Hash::new(policy_id.try_into().expect("Not Correct Length")),
token_name,
1,
)
.unwrap();
calculate_min_required_utxo(staging_output)
}
pub fn wallet_minimum_lovelace_with_assets(tokens: Assets) -> u64 {
let mut staging_output: Output = Output::new(address::wallet_contract(true, 1), 5_000_000)
.set_inline_datum(
Register::create(schnorr::random_scalar())
.rerandomize()
.to_vec(),
);
for asset in tokens.items {
staging_output = staging_output
.add_asset(asset.policy_id, asset.token_name, asset.amount)
.unwrap();
}
calculate_min_required_utxo(staging_output)
}
pub fn address_minimum_lovelace_with_assets(address: &str, tokens: Assets) -> u64 {
let addr: Address = Address::from_bech32(address).unwrap();
let mut staging_output: Output = Output::new(addr, 5_000_000);
for asset in tokens.items {
staging_output = staging_output
.add_asset(asset.policy_id, asset.token_name, asset.amount)
.unwrap();
}
calculate_min_required_utxo(staging_output)
}