Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 93 additions & 44 deletions seedelf-platform/seedelf-cli/src/commands/fund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ use seedelf_core::utxos;
use seedelf_crypto::register::Register;
use seedelf_display::{display, text_coloring};
use seedelf_koios::koios::{UtxoResponse, extract_bytes_with_logging};
use serde::Serialize;

#[derive(Serialize)]
pub struct FundSeedelfOutput {
pub tx_cbor: String,
pub tx_fee: u64,
pub usable_utxos: Vec<UtxoResponse>,
}

/// Struct to hold command-specific arguments
#[derive(Args)]
Expand Down Expand Up @@ -130,41 +138,91 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
bail!("Supplied Address Is Incorrect");
}

let FundSeedelfOutput {
tx_cbor,
tx_fee,
usable_utxos,
} = build_fund_seedelf(
config,
network_flag,
args.address,
args.seedelf,
args.lovelace.unwrap_or(minimum_lovelace),
selected_tokens,
)
.await;

if usable_utxos.is_empty() {
bail!("Not Enough Lovelace/Tokens");
}

println!(
"{} {}",
"\nTx Size Fee:".bright_blue(),
tx_fee.to_string().bright_white()
);

println!("\nTx Cbor: {}", tx_cbor.clone().white());

// inject the tx cbor into the local webserver to prompt the wallet
display::webserver_address();
web_server::run_web_server(tx_cbor, network_flag).await;
text_coloring::display_purple("Server has stopped.");

Ok(())
}

pub async fn build_fund_seedelf(
config: Config,
network_flag: bool,
user_address: String,
seedelf: String,
lovelace: u64,
selected_tokens: Assets,
) -> FundSeedelfOutput {
// we need to make sure that the network flag and the address provided makes sense here
let addr: Address = Address::from_bech32(user_address.as_str()).unwrap();

// we need this as the address type and not the shelley
let wallet_addr: Address =
address::wallet_contract(network_flag, config.contract.wallet_contract_hash);

// this is used to calculate the real fee
let mut draft_tx: StagingTransaction = StagingTransaction::new();

// we need about 2 ada for change so just add that to the amount
let lovelace: u64 = args.lovelace.unwrap_or(minimum_lovelace);
let lovelace_goal: u64 = lovelace;
let every_utxo_at_script: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag)
.await
.unwrap_or_default();

// utxos
let every_utxo: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?;
let seedelf_utxo: UtxoResponse = utxos::find_seedelf_utxo(
args.seedelf.clone(),
let seedelf_utxo: UtxoResponse = match utxos::find_seedelf_utxo(
seedelf.clone(),
&config.contract.seedelf_policy_id,
every_utxo,
)?
.ok_or("Seedelf Not Found".to_string())
.unwrap();
every_utxo_at_script,
) {
Ok(Some(utxo)) => utxo,
_ => UtxoResponse::default(),
};

let seedelf_datum: Register = extract_bytes_with_logging(&seedelf_utxo.inline_datum)
.ok_or("Not Register Type".to_string())
.unwrap();

let every_utxo: Vec<UtxoResponse> =
utxos::get_address_utxos(&args.address, network_flag).await?;
let all_utxos: Vec<UtxoResponse> = utxos::collect_address_utxos(every_utxo)?;
.unwrap_or_default();

let every_utxo_at_address: Vec<UtxoResponse> =
utxos::get_address_utxos(&user_address, network_flag)
.await
.unwrap_or_default();
// all non collateral utxos, assume 5 ada for collateral
let every_non_collatreal_utxo: Vec<UtxoResponse> =
utxos::collect_address_utxos(every_utxo_at_address).unwrap_or_default();
let usable_utxos: Vec<UtxoResponse> =
utxos::select(all_utxos, lovelace_goal, selected_tokens.clone())?;
utxos::select(every_non_collatreal_utxo, lovelace, selected_tokens.clone())
.unwrap_or_default();

if usable_utxos.is_empty() {
bail!("Not Enough Lovelace/Tokens");
}
let (total_lovelace, tokens) = utxos::assets_of(usable_utxos.clone()).unwrap_or_default();
let change_tokens: Assets = tokens.separate(selected_tokens.clone()).unwrap_or_default();

// add usable wallet utxos as inputs
for utxo in usable_utxos.clone() {
// draft and raw are built the same here
draft_tx = draft_tx.input(Input::new(
Expand All @@ -178,18 +236,14 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
));
}

let (total_lovelace, tokens) = utxos::assets_of(usable_utxos)?;
// tokens tha need to be put into the change output
let change_tokens: Assets = tokens.separate(selected_tokens.clone())?;
// if the seedelf isn't found then error
if total_lovelace < lovelace_goal {
bail!("Not Enough Lovelace/Tokens");
}

// This is some semi legit fee to be used to estimate it
let tmp_fee: u64 = 200_000;

let datum_vector: Vec<u8> = seedelf_datum.rerandomize()?.to_vec()?;
let datum_vector: Vec<u8> = seedelf_datum
.rerandomize()
.unwrap_or_default()
.to_vec()
.unwrap_or_default();
let mut fund_output: Output =
Output::new(wallet_addr.clone(), lovelace).set_inline_datum(datum_vector.clone());
for asset in selected_tokens.items.clone() {
Expand All @@ -208,7 +262,7 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
let mut number_of_change_utxo: usize = change_token_per_utxo.len();
let mut lovelace_amount: u64 = total_lovelace;
for (i, change) in change_token_per_utxo.iter().enumerate() {
let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone())?;
let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone()).unwrap_or_default();
let change_lovelace: u64 = if i == number_of_change_utxo - 1 {
// this is the last one or the only one
lovelace_amount = lovelace_amount - lovelace - tmp_fee;
Expand Down Expand Up @@ -241,6 +295,7 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
for i in 0..number_of_change_utxo {
raw_tx = raw_tx.remove_output(number_of_change_utxo - i);
}

// let mut raw_tx: StagingTransaction = draft_tx.clone().remove_output(1).clear_fee();
// build an intermediate tx for fee estimation
let intermediate_tx: BuiltTransaction = draft_tx.build_conway_raw().unwrap();
Expand All @@ -261,11 +316,6 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
// floor division means its safer to just add 1 lovelace
let tx_fee: u64 =
fees::compute_linear_fee_policy(tx_size, &(fees::PolicyParams::default())) + 1;
println!(
"{} {}",
"\nTx Size Fee:".bright_blue(),
tx_fee.to_string().bright_white()
);

// a max tokens per change output here
let change_token_per_utxo: Vec<Assets> = change_tokens
Expand All @@ -274,7 +324,7 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
let number_of_change_utxo: usize = change_token_per_utxo.len();
let mut lovelace_amount: u64 = total_lovelace;
for (i, change) in change_token_per_utxo.iter().enumerate() {
let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone())?;
let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone()).unwrap_or_default();
let change_lovelace: u64 = if i == number_of_change_utxo - 1 {
// this is the last one or the only one
lovelace_amount = lovelace_amount - lovelace - tx_fee;
Expand Down Expand Up @@ -307,12 +357,11 @@ pub async fn run(args: FundArgs, network_flag: bool, variant: u64) -> Result<()>
let tx: BuiltTransaction = raw_tx.build_conway_raw().unwrap();

let tx_cbor: String = hex::encode(tx.tx_bytes);
println!("\nTx Cbor: {}", tx_cbor.clone().white());

// inject the tx cbor into the local webserver to prompt the wallet
display::webserver_address();
web_server::run_web_server(tx_cbor, network_flag).await;
text_coloring::display_purple("Server has stopped.");

Ok(())
// fill this out as we need it
FundSeedelfOutput {
tx_cbor,
tx_fee,
usable_utxos,
}
}
12 changes: 1 addition & 11 deletions seedelf-platform/seedelf-cli/src/commands/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,23 +157,13 @@ pub async fn build_remove_seedelf(
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag)
.await
.unwrap_or_default();

// for (i, u) in every_utxo.iter().enumerate() {
// println!(
// "[GUI] UTxO {}: tx_hash={} datum={:?}",
// i,
// u.tx_hash,
// u.inline_datum
// );
// }
// println!("Seedelf: {:}", seedelf);
let seedelf_utxo: UtxoResponse = match utxos::find_seedelf_utxo(
seedelf.clone(),
&config.contract.seedelf_policy_id,
every_utxo,
) {
Ok(Some(utxo)) => utxo,
_ => UtxoResponse::default()
_ => UtxoResponse::default(),
};

let seedelf_datum: Register = extract_bytes_with_logging(&seedelf_utxo.inline_datum)
Expand Down
10 changes: 5 additions & 5 deletions seedelf-platform/seedelf-core/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ pub fn extract_budgets(value: &Value) -> Vec<(u64, u64)> {
// Ensure the value contains the expected "result" array
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)) = (
if let Some(budget) = item.get("budget")
&& 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.push((cpu, memory));
}
}
}
Expand Down
34 changes: 17 additions & 17 deletions seedelf-platform/seedelf-core/src/utxos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,24 +315,24 @@ pub fn assets_of(utxos: Vec<UtxoResponse>) -> Result<(u64, Assets)> {
let value: u64 = string_to_u64(utxo.value.clone()).context("Invalid UTxO Value")?;
current_lovelace_sum += value;

if let Some(assets) = utxo.clone().asset_list {
if !assets.is_empty() {
let mut utxo_assets: Assets = Assets::new();

for token in assets.clone() {
let new_asset = Asset::new(
token.policy_id,
token.asset_name,
string_to_u64(token.quantity).context("Invalid Token Quantity")?,
)
.context("Fail To Construct Asset")?;
utxo_assets = utxo_assets.add(new_asset).context("Can't Add Assets")?;
}

found_assets = found_assets
.merge(utxo_assets.clone())
.context("Can't Merge Assets")?;
if let Some(assets) = utxo.clone().asset_list
&& !assets.is_empty()
{
let mut utxo_assets: Assets = Assets::new();

for token in assets.clone() {
let new_asset = Asset::new(
token.policy_id,
token.asset_name,
string_to_u64(token.quantity).context("Invalid Token Quantity")?,
)
.context("Fail To Construct Asset")?;
utxo_assets = utxo_assets.add(new_asset).context("Can't Add Assets")?;
}

found_assets = found_assets
.merge(utxo_assets.clone())
.context("Can't Merge Assets")?;
}
}
Ok((current_lovelace_sum, found_assets))
Expand Down
36 changes: 36 additions & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/commands/fund.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use seedelf_cli::commands::fund::{FundSeedelfOutput, build_fund_seedelf};
use seedelf_core::assets::Assets;
use seedelf_core::constants::{Config, VARIANT, get_config};

#[tauri::command(async)]
pub async fn fund_seedelf(
network_flag: bool,
user_address: String,
seedelf: String,
lovelace: u64,
) -> String {
let config: Config = match get_config(VARIANT, network_flag) {
Some(c) => c,
None => {
return String::new();
}
};
let FundSeedelfOutput {
tx_cbor,
usable_utxos,
..
} = build_fund_seedelf(
config,
network_flag,
user_address,
seedelf,
lovelace,
// todo add in assets
Assets::new(),
)
.await;
if usable_utxos.is_empty() {
return String::new();
}
tx_cbor
}
1 change: 1 addition & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod create;
pub mod fund;
pub mod remove;
7 changes: 4 additions & 3 deletions seedelf-platform/seedelf-gui/src-tauri/src/commands/remove.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use seedelf_core::constants::{Config, VARIANT, get_config};
use crate::session;
use seedelf_cli::commands::remove::{build_remove_seedelf, RemoveSeedelfOutput};
use seedelf_cli::commands::remove::{RemoveSeedelfOutput, build_remove_seedelf};
use seedelf_core::constants::{Config, VARIANT, get_config};

#[tauri::command(async)]
pub async fn remove_seedelf(network_flag: bool, addr: String, seedelf: String) -> String {
Expand All @@ -18,7 +18,8 @@ pub async fn remove_seedelf(network_flag: bool, addr: String, seedelf: String) -
spend_cpu_units,
spend_mem_units,
..
} = match session::with_key(|sk| build_remove_seedelf(config, network_flag, addr, seedelf, *sk)) {
} = match session::with_key(|sk| build_remove_seedelf(config, network_flag, addr, seedelf, *sk))
{
Ok(v) => v.await,
_ => return String::new(),
};
Expand Down
4 changes: 4 additions & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod commands;
pub mod session;
pub mod setup;
pub mod types;
pub mod utxos;
pub mod wallet;
pub mod webserver;

Expand All @@ -25,11 +26,14 @@ pub fn run() {
wallet::get_owned_seedelfs,
wallet::get_lovelace_balance,
wallet::get_wallet_history,
// utxos.rs
utxos::get_every_seedelf,
// address.rs
address::is_not_a_script,
// commands
commands::create::create_seedelf,
commands::remove::remove_seedelf,
commands::fund::fund_seedelf,
// webserver.rs
webserver::open_web_server,
webserver::close_web_server
Expand Down
16 changes: 16 additions & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/utxos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use seedelf_core::constants::{Config, VARIANT, get_config};
use seedelf_core::utxos;
use seedelf_koios::koios::UtxoResponse;

#[tauri::command(async)]
pub async fn get_every_seedelf(network_flag: bool, all_utxos: Vec<UtxoResponse>) -> Vec<String> {
let config: Config = match get_config(VARIANT, network_flag) {
Some(c) => c,
None => {
return Vec::new();
}
};

utxos::find_all_seedelfs(String::new(), &config.contract.seedelf_policy_id, all_utxos)
.unwrap_or_default()
}
Loading