From 04ae1970a09a6e6ee5bcee3ada60011ea4a7807e Mon Sep 17 00:00:00 2001 From: logicalmechanism Date: Sat, 9 Aug 2025 15:50:42 -0700 Subject: [PATCH 1/5] need to refactor out sweep --- .../seedelf-cli/src/commands/sweep.rs | 17 ++++++++++ .../src-tauri/src/commands/extract.rs | 34 +++++++++++++++++++ .../seedelf-gui/src-tauri/src/commands/mod.rs | 1 + .../src-tauri/src/commands/send.rs | 2 +- .../seedelf-gui/src-tauri/src/lib.rs | 1 + .../seedelf-gui/src/pages/Wallet/Extract.tsx | 2 +- .../src/pages/Wallet/transactions.ts | 14 ++++++++ 7 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs diff --git a/seedelf-platform/seedelf-cli/src/commands/sweep.rs b/seedelf-platform/seedelf-cli/src/commands/sweep.rs index f8b92c1..19b8854 100644 --- a/seedelf-platform/seedelf-cli/src/commands/sweep.rs +++ b/seedelf-platform/seedelf-cli/src/commands/sweep.rs @@ -30,6 +30,11 @@ use seedelf_koios::koios::{ witness_collateral, }; +pub struct SweepSeedelfOutput { + pub tx_cbor: String, + pub tx_hash: String, +} + /// Struct to hold command-specific arguments #[derive(Args)] pub struct SweepArgs { @@ -625,3 +630,15 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() Ok(()) } + +pub async fn build_sweep_seedelf( + config: Config, + network_flag: bool, + address: String, + lovelace: u64, + selected_tokens: Assets, + selected_utxos: Option>, + scalar: Scalar, +) -> SweepSeedelfOutput { + SweepSeedelfOutput {tx_cbor: String::new(), tx_hash: String::new()} +} \ No newline at end of file diff --git a/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs b/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs new file mode 100644 index 0000000..a70d1c1 --- /dev/null +++ b/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs @@ -0,0 +1,34 @@ +// core named this sweep, but in the gui it will be extract +use crate::session; +use seedelf_cli::commands::sweep::{SweepSeedelfOutput, build_sweep_seedelf}; +use seedelf_core::assets::Assets; +use seedelf_core::constants::{Config, VARIANT, get_config}; + +#[tauri::command(async)] +pub async fn extract_seedelf(network_flag: bool, address: String, lovelace: u64) -> String { + let config: Config = match get_config(VARIANT, network_flag) { + Some(c) => c, + None => { + return String::new(); + } + }; + let SweepSeedelfOutput { + tx_hash, + .. + } = match session::with_key(|sk| { + build_sweep_seedelf( + config, + network_flag, + address, + lovelace, + Assets::new(), + None, + *sk, + ) + }) { + Ok(v) => v.await, + _ => return String::new(), + }; + + tx_hash +} diff --git a/seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs b/seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs index 3f10544..ff79c73 100644 --- a/seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs +++ b/seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs @@ -1,4 +1,5 @@ pub mod create; +pub mod extract; pub mod fund; pub mod remove; pub mod send; diff --git a/seedelf-platform/seedelf-gui/src-tauri/src/commands/send.rs b/seedelf-platform/seedelf-gui/src-tauri/src/commands/send.rs index 088cfed..d431355 100644 --- a/seedelf-platform/seedelf-gui/src-tauri/src/commands/send.rs +++ b/seedelf-platform/seedelf-gui/src-tauri/src/commands/send.rs @@ -1,4 +1,4 @@ -// core named this transfer, but in the gui it will send +// core named this transfer, but in the gui it will be send use crate::session; use seedelf_cli::commands::transfer::{TransferSeedelfOutput, build_transfer_seedelf}; use seedelf_core::assets::Assets; diff --git a/seedelf-platform/seedelf-gui/src-tauri/src/lib.rs b/seedelf-platform/seedelf-gui/src-tauri/src/lib.rs index 826091e..21d5aea 100644 --- a/seedelf-platform/seedelf-gui/src-tauri/src/lib.rs +++ b/seedelf-platform/seedelf-gui/src-tauri/src/lib.rs @@ -36,6 +36,7 @@ pub fn run() { commands::remove::remove_seedelf, commands::fund::fund_seedelf, commands::send::send_seedelf, + commands::extract::extract_seedelf, // constants constants::get_seedelf_policy_id, // webserver.rs diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx index 67d326d..f244bc2 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx @@ -2,7 +2,7 @@ export function Extract() { return ( -
+

Extract

Remove some funds from the wallet

diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts b/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts index bc1b90e..73bdc9c 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts @@ -55,3 +55,17 @@ export async function sendSeedelf( lovelace: lovelace, }); } + + +export async function extractSeedelf( + network: Network, + address: string, + lovelace: number, +): Promise { + const flag = castNetwork(network); + return await invoke("extract_seedelf", { + networkFlag: flag, + address: address, + lovelace: lovelace, + }); +} \ No newline at end of file From a0382dc0c88128f5f7b6344e51693fd6c42a9165 Mon Sep 17 00:00:00 2001 From: logicalmechanism Date: Sat, 9 Aug 2025 20:53:31 -0700 Subject: [PATCH 2/5] front looks fine, need to do the refactor now --- .../seedelf-gui/src/pages/Wallet/Extract.tsx | 181 +++++++++++++++++- 1 file changed, 178 insertions(+), 3 deletions(-) diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx index f244bc2..6abcbdf 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx @@ -1,10 +1,185 @@ -// extract funds from the wallet +import { useState } from "react"; +import { + ShowNotification, + NotificationVariant, +} from "@/components/ShowNotification"; +import { ConfirmationModal } from "@/components/ConfirmationModal"; +import { ExplorerLinkModal } from "@/components/ExplorerLinkModal"; +import { useNetwork } from "@/types/network"; +import { TextField } from "@/components/TextField"; +import { NumberField } from "@/components/NumberField"; +import { Checkbox } from "@/components/Checkbox"; +import { SearchCheck } from "lucide-react"; +import { extractSeedelf } from "./transactions"; +import { colorClasses } from "./colors"; +import { isNotAScript } from "./api"; + +import { useOutletContext } from "react-router"; +import { OutletContextType } from "@/types/layout"; export function Extract() { + const [message, setMessage] = useState(null); + const [variant, setVariant] = useState("error"); + + const [address, setAddress] = useState(""); + const [ada, setAda] = useState(0); + + const { network } = useNetwork(); + const [addressValid, setAddressValid] = useState(false); + const [submitting, setSubmitting] = useState(false); + const [isSendAll, setIsSendAll] = useState(false); + + const { lovelace } = useOutletContext(); + + const [txHash, setTxHash] = useState(""); + + const [showConfirmationModal, setShowConfirmationModal] = useState(false); + const [showExplorerLinkModal, setShowExplorerLinkModal] = useState(false); + + const handleAddressValid = async (a: string) => { + setVariant("error"); + if (!a.trim()) return setMessage("Wallet address is required."); + if (network == "mainnet" && !a.includes("addr1")) + return setMessage("Incorrect Mainnet Address Format"); + if (network == "preprod" && !a.includes("addr_test1")) + return setMessage("Incorrect Pre-Production Address Format"); + const notScript = await isNotAScript(a); + if (!notScript) return setMessage("Address Is A Script"); + setVariant("info"); + setMessage("Address is valid"); + setAddressValid(true); + }; + + const handleClear = () => { + setAddress(""); + setAddressValid(false); + setAda(0); + setIsSendAll(false); + }; + + const handleSubmit = async () => { + setVariant("error"); + const lovelace = ada * 1_000_000; + + // should be good to run the build tx function now + try { + setVariant("info"); + setMessage("Building Fund Seedelf Transaction"); + const _txHash = await extractSeedelf(network, address, lovelace); + if (_txHash) { + setTxHash(_txHash); + setShowExplorerLinkModal(true); + handleClear(); + } + } catch (e: any) { + setVariant("error"); + setMessage(e as string); + } finally { + setSubmitting(false); + } + }; + return (
-

Extract

-

Remove some funds from the wallet

+

Extract From A Seedelf

+ + + + { + setShowExplorerLinkModal(false); + }} + /> + + { + handleSubmit(); + setShowConfirmationModal(false); + }} + onCancel={() => { + setShowConfirmationModal(false); + }} + /> + +
+
+ { + const next = e.target.value; + setAddress(next); + handleAddressValid(next); + }} + disabled={submitting} + maxLength={108} + /> + + +
+
+ +
+ +
+ +
+ { + if (isSendAll) { + setAddress(""); + setAddressValid(false); + setIsSendAll(false); + } else { + setAddress(address); + setAda(lovelace); + setIsSendAll(true); + } + }} + baseColor={colorClasses.green.text} + /> +
+ + + {(address.length != 0 || ada > 0) && ( + + )} +
+
); } From 50f4c6c4a91ecbc72a2476c327c3b1b94b963e5b Mon Sep 17 00:00:00 2001 From: logicalmechanism Date: Sat, 9 Aug 2025 21:51:51 -0700 Subject: [PATCH 3/5] extract seems to be working --- .../seedelf-cli/src/commands/sweep.rs | 309 ++++++++++-------- seedelf-platform/seedelf-core/src/assets.rs | 16 +- .../src-tauri/src/commands/extract.rs | 13 +- .../seedelf-gui/src/pages/Wallet/Extract.tsx | 6 +- .../seedelf-gui/src/pages/Wallet/Send.tsx | 2 +- .../src/pages/Wallet/transactions.ts | 2 + 6 files changed, 207 insertions(+), 141 deletions(-) diff --git a/seedelf-platform/seedelf-cli/src/commands/sweep.rs b/seedelf-platform/seedelf-cli/src/commands/sweep.rs index 19b8854..564437f 100644 --- a/seedelf-platform/seedelf-cli/src/commands/sweep.rs +++ b/seedelf-platform/seedelf-cli/src/commands/sweep.rs @@ -33,6 +33,11 @@ use seedelf_koios::koios::{ pub struct SweepSeedelfOutput { pub tx_cbor: String, pub tx_hash: String, + pub tx_fee: u64, + pub compute_fee: u64, + pub script_reference_fee: u64, + pub total_fee: u64, + pub usable_utxos: Vec, } /// Struct to hold command-specific arguments @@ -51,7 +56,7 @@ pub struct SweepArgs { #[arg( short = 'l', long, - help = "The amount of Lovelace being sent to the address. Cannt be used with --all", + help = "The amount of Lovelace being sent to the address. Cannot be used with --all", display_order = 2 )] lovelace: Option, @@ -205,6 +210,92 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() bail!("Supplied Address Is Incorrect"); } + let minimum_lovelace: u64 = wallet_minimum_lovelace_with_assets(selected_tokens.clone())?; + let scalar: Scalar = setup::unlock_wallet_interactive(); + + let SweepSeedelfOutput { + tx_cbor, + tx_hash, + tx_fee, + compute_fee, + script_reference_fee, + total_fee, + usable_utxos, + } = build_sweep_seedelf( + config, + network_flag, + outbound_address, + args.lovelace.unwrap_or(minimum_lovelace), + selected_tokens, + args.utxos, + scalar, + args.all, + ) + .await; + + if usable_utxos.is_empty() { + bail!("No Usuable UTxOs Found"); + } + + println!( + "{} {}", + "\nTx Size Fee:".bright_blue(), + tx_fee.to_string().bright_white() + ); + + println!( + "{} {}", + "Compute Fee:".bright_blue(), + compute_fee.to_string().bright_white() + ); + + println!( + "{} {}", + "Script Reference Fee:".bright_blue(), + script_reference_fee.to_string().bright_white() + ); + + println!( + "{} {}", + "Total Fee:".bright_blue(), + total_fee.to_string().bright_white() + ); + + println!("\nTx Cbor: {}", hex::encode(tx_cbor.clone()).white()); + + if tx_hash.is_empty() { + println!("\nTransaction Successfully Failed!"); + } else { + println!("\nTransaction Successfully Submitted!"); + println!("\nTx Hash: {}", tx_hash.bright_cyan()); + if network_flag { + println!( + "{}", + format!("\nhttps://preprod.cardanoscan.io/transaction/{}", tx_hash).bright_purple() + ); + } else { + println!( + "{}", + format!("\nhttps://cardanoscan.io/transaction/{}", tx_hash).bright_purple() + ); + } + } + + Ok(()) +} + +pub async fn build_sweep_seedelf( + config: Config, + network_flag: bool, + address: String, + lovelace: u64, + selected_tokens: Assets, + selected_utxos: Option>, + scalar: Scalar, + send_all: bool, +) -> SweepSeedelfOutput { + let addr: Address = Address::from_bech32(&address).unwrap(); + let collat_addr: Address = address::collateral_address(network_flag); let wallet_addr: Address = address::wallet_contract(network_flag, config.contract.wallet_contract_hash); @@ -215,43 +306,40 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() let mut input_vector: Vec = Vec::new(); let mut register_vector: Vec = Vec::new(); - // we will assume lovelace only right now - let minimum_lovelace: u64 = wallet_minimum_lovelace_with_assets(selected_tokens.clone())?; - let lovelace_goal: u64 = args.lovelace.unwrap_or(minimum_lovelace); - - // if there is change going back then we need this to rerandomize a datum - let scalar: Scalar = setup::unlock_wallet_interactive(); + let minimum_lovelace: u64 = + wallet_minimum_lovelace_with_assets(selected_tokens.clone()).unwrap_or_default(); + let lovelace_goal: u64 = if lovelace < minimum_lovelace { + minimum_lovelace + } else { + lovelace + }; let every_utxo: Vec = - utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?; + utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag) + .await + .unwrap_or_default(); let owned_utxos: Vec = - utxos::collect_wallet_utxos(scalar, &config.contract.seedelf_policy_id, every_utxo)?; - let usable_utxos: Vec = if args.all { + utxos::collect_wallet_utxos(scalar, &config.contract.seedelf_policy_id, every_utxo) + .unwrap_or_default(); + + let usable_utxos: Vec = if send_all { owned_utxos } else { // if not selecting utxos then select from the owned utxos else use the utxos provided - if args.utxos.is_none() { + if selected_utxos.is_none() { // we will assume that the change will required ~2 ADA and the fee about ~0.5 ADA - utxos::select(owned_utxos, lovelace_goal, selected_tokens.clone())? + utxos::select(owned_utxos, lovelace_goal, selected_tokens.clone()).unwrap_or_default() } else { // assumes the utxos hold the correct tokens else it will error downstream - match utxos::parse_tx_utxos(args.utxos.unwrap_or_default()) { + match utxos::parse_tx_utxos(selected_utxos.unwrap_or_default()) { Ok(parsed) => utxos::filter_utxos(owned_utxos, parsed), - Err(e) => { - eprintln!("Unable To Parse UTxOs Error: {e}"); - // nothing works if you are not spending anything, this could be an exit - Vec::new() - } + Err(_) => Vec::new(), } } }; - if usable_utxos.is_empty() { - bail!("No Usuable UTxOs Found"); - } - - let (total_lovelace_found, tokens) = utxos::assets_of(usable_utxos.clone())?; - let change_tokens: Assets = tokens.separate(selected_tokens.clone())?; + let (total_lovelace_found, tokens) = utxos::assets_of(usable_utxos.clone()).unwrap_or_default(); + let change_tokens: Assets = tokens.separate(selected_tokens.clone()).unwrap_or_default(); for utxo in usable_utxos.clone() { let this_input: Input = Input::new( @@ -285,14 +373,14 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() let mut sweep_output: Output = Output::new( addr.clone(), - if args.all { + if send_all { total_lovelace_found - tmp_fee } else { lovelace_goal }, ); - if args.all { + if send_all { for asset in tokens.items.clone() { sweep_output = sweep_output .add_asset(asset.policy_id, asset.token_name, asset.amount) @@ -334,11 +422,17 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() .split(MAXIMUM_TOKENS_PER_UTXO.try_into().unwrap()); let mut number_of_change_utxo: usize = change_token_per_utxo.len(); let mut lovelace_amount: u64 = total_lovelace_found; - if !args.all { + if !send_all { // a max tokens per change output here for (i, change) in change_token_per_utxo.iter().enumerate() { - let datum_vector: Vec = Register::create(scalar)?.rerandomize()?.to_vec()?; - let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone())?; + let datum_vector: Vec = Register::create(scalar) + .unwrap_or_default() + .rerandomize() + .unwrap_or_default() + .to_vec() + .unwrap_or_default(); + 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_goal - tmp_fee; @@ -360,9 +454,14 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() } } - if number_of_change_utxo == 0 && !args.all { + if number_of_change_utxo == 0 && !send_all { // no tokens so we just need to account for the lovelace going back - let datum_vector: Vec = Register::create(scalar)?.rerandomize()?.to_vec()?; + let datum_vector: Vec = Register::create(scalar) + .unwrap_or_default() + .rerandomize() + .unwrap_or_default() + .to_vec() + .unwrap_or_default(); let change_lovelace: u64 = lovelace_amount - lovelace_goal - tmp_fee; let change_output: Output = Output::new(wallet_addr.clone(), change_lovelace) .set_inline_datum(datum_vector.clone()); @@ -377,11 +476,12 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() .zip(register_vector.clone().into_iter()) { let r: Scalar = random_scalar(); - let (z, g_r) = create_proof(datum, scalar, pkh.clone(), r)?; - let spend_redeemer_vector = data_structures::create_spend_redeemer(z, g_r, pkh.clone()); + let (z, g_r) = create_proof(datum, scalar, pkh.clone(), r).unwrap_or_default(); + let spend_redeemer_vector = + data_structures::create_spend_redeemer(z, g_r, pkh.clone()).unwrap_or_default(); draft_tx = draft_tx.add_spend_redeemer( input, - spend_redeemer_vector?.clone(), + spend_redeemer_vector.clone(), Some(pallas_txbuilder::ExUnits { mem: 14_000_000, steps: 10_000_000_000, @@ -391,7 +491,7 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() let mut raw_tx: StagingTransaction = draft_tx.clone().clear_fee().clear_collateral_output(); - if !args.all { + if !send_all { for i in 0..number_of_change_utxo + 1 { raw_tx = raw_tx.remove_output(number_of_change_utxo - i); } @@ -418,10 +518,7 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() let budgets: Vec<(u64, u64)> = extract_budgets(&execution_units); budgets } - Err(err) => { - eprintln!("Failed to evaluate transaction: {err}"); - std::process::exit(1); - } + Err(_) => Vec::new(), }; // we can fake the signature here to get the correct tx size @@ -439,26 +536,11 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() .try_into() .unwrap(); let tx_fee = fees::compute_linear_fee_policy(tx_size, &(fees::PolicyParams::default())); - println!( - "{} {}", - "\nTx Size Fee:".bright_blue(), - tx_fee.to_string().bright_white() - ); // This probably should be a function let compute_fee: u64 = total_computation_fee(budgets.clone()); - println!( - "{} {}", - "Compute Fee:".bright_blue(), - compute_fee.to_string().bright_white() - ); let script_reference_fee: u64 = config.contract.wallet_contract_size * 15; - println!( - "{} {}", - "Script Reference Fee:".bright_blue(), - script_reference_fee.to_string().bright_white() - ); // total fee is the sum of everything let mut total_fee: u64 = tx_fee + compute_fee + script_reference_fee; @@ -468,22 +550,17 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() } else { total_fee }; - println!( - "{} {}", - "Total Fee:".bright_blue(), - total_fee.to_string().bright_white() - ); let mut sweep_output: Output = Output::new( addr.clone(), - if args.all { + if send_all { total_lovelace_found - total_fee } else { lovelace_goal }, ); - if args.all { + if send_all { for asset in tokens.items.clone() { sweep_output = sweep_output .add_asset(asset.policy_id, asset.token_name, asset.amount) @@ -510,12 +587,18 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() .clone() .split(MAXIMUM_TOKENS_PER_UTXO.try_into().unwrap()); let number_of_change_utxo: usize = change_token_per_utxo.len(); - if !args.all { + if !send_all { // a max tokens per change output here let mut lovelace_amount: u64 = total_lovelace_found; for (i, change) in change_token_per_utxo.iter().enumerate() { - let datum_vector: Vec = Register::create(scalar)?.rerandomize()?.to_vec()?; - let minimum: u64 = wallet_minimum_lovelace_with_assets(change.clone())?; + let datum_vector: Vec = Register::create(scalar) + .unwrap_or_default() + .rerandomize() + .unwrap_or_default() + .to_vec() + .unwrap_or_default(); + 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_goal - total_fee; @@ -537,9 +620,14 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() } } - if number_of_change_utxo == 0 && !args.all { + if number_of_change_utxo == 0 && !send_all { // no tokens so we just need to account for the lovelace going back - let datum_vector: Vec = Register::create(scalar)?.rerandomize()?.to_vec()?; + let datum_vector: Vec = Register::create(scalar) + .unwrap_or_default() + .rerandomize() + .unwrap_or_default() + .to_vec() + .unwrap_or_default(); let change_lovelace: u64 = lovelace_amount - lovelace_goal - total_fee; let change_output: Output = Output::new(wallet_addr.clone(), change_lovelace) .set_inline_datum(datum_vector.clone()); @@ -553,11 +641,11 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() .zip(budgets.clone().into_iter()) { let r: Scalar = random_scalar(); - let (z, g_r) = create_proof(datum, scalar, pkh.clone(), r)?; + let (z, g_r) = create_proof(datum, scalar, pkh.clone(), r).unwrap_or_default(); let spend_redeemer_vector = data_structures::create_spend_redeemer(z, g_r, pkh.clone()); raw_tx = raw_tx.add_spend_redeemer( input, - spend_redeemer_vector?.clone(), + spend_redeemer_vector.unwrap_or_default().clone(), Some(pallas_txbuilder::ExUnits { mem, steps: cpu }), ) } @@ -568,77 +656,36 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() let witness_public_key: PublicKey = PublicKey::from(COLLATERAL_PUBLIC_KEY); - match witness_collateral(tx_cbor.clone(), network_flag).await { + let signed_tx_cbor: BuiltTransaction = match witness_collateral(tx_cbor.clone(), network_flag) + .await + { Ok(witness) => { let witness_cbor = witness.get("witness").and_then(|v| v.as_str()).unwrap(); let witness_sig = &witness_cbor[witness_cbor.len() - 128..]; let witness_vector: [u8; 64] = hex::decode(witness_sig).unwrap().try_into().unwrap(); - let signed_tx_cbor = tx - .sign(pallas_wallet::PrivateKey::from(one_time_secret_key.clone())) + tx.sign(PrivateKey::from(one_time_secret_key.clone())) .unwrap() .add_signature(witness_public_key, witness_vector) - .unwrap(); + .unwrap() + } + _ => tx, + }; - println!( - "\nTx Cbor: {}", - hex::encode(signed_tx_cbor.tx_bytes.clone()).white() - ); + let tx_hash = match submit_tx(hex::encode(signed_tx_cbor.clone().tx_bytes), network_flag).await + { + Ok(response) => response.as_str().unwrap_or("default").to_string(), + Err(_) => String::new(), + }; - match submit_tx(hex::encode(signed_tx_cbor.tx_bytes), network_flag).await { - Ok(response) => { - if let Some(_error) = response.get("contents") { - println!("\nError: {response}"); - std::process::exit(1); - } - println!("\nTransaction Successfully Submitted!"); - println!( - "\nTx Hash: {}", - response.as_str().unwrap_or("default").bright_cyan() - ); - if network_flag { - println!( - "{}", - format!( - "\nhttps://preprod.cardanoscan.io/transaction/{}", - response.as_str().unwrap_or("default") - ) - .bright_purple() - ); - } else { - println!( - "{}", - format!( - "\nhttps://cardanoscan.io/transaction/{}", - response.as_str().unwrap_or("default") - ) - .bright_purple() - ); - } - } - Err(err) => { - eprintln!("Failed to submit tx: {err}"); - std::process::exit(1); - } - } - } - Err(err) => { - eprintln!("Failed to fetch UTxOs: {err}"); - std::process::exit(1); - } + // + SweepSeedelfOutput { + tx_cbor, + tx_hash, + tx_fee, + compute_fee, + script_reference_fee, + total_fee, + usable_utxos, } - - Ok(()) } - -pub async fn build_sweep_seedelf( - config: Config, - network_flag: bool, - address: String, - lovelace: u64, - selected_tokens: Assets, - selected_utxos: Option>, - scalar: Scalar, -) -> SweepSeedelfOutput { - SweepSeedelfOutput {tx_cbor: String::new(), tx_hash: String::new()} -} \ No newline at end of file diff --git a/seedelf-platform/seedelf-core/src/assets.rs b/seedelf-platform/seedelf-core/src/assets.rs index d29ed72..5ab045b 100644 --- a/seedelf-platform/seedelf-core/src/assets.rs +++ b/seedelf-platform/seedelf-core/src/assets.rs @@ -14,6 +14,19 @@ pub struct Asset { pub amount: u64, } +impl Default for Asset { + fn default() -> Self { + let blank = Hash::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + Self { + policy_id: blank, + token_name: blank.to_vec(), + amount: 0, + } + } +} + impl Asset { /// Creates a new `Asset` instance. /// @@ -25,7 +38,8 @@ impl Asset { pub fn new(policy_id: String, token_name: String, amount: u64) -> Result { Ok(Self { policy_id: Hash::new( - hex::decode(policy_id)? + hex::decode(policy_id) + .unwrap_or_default() .as_slice() .try_into() .map_err(|e| anyhow::anyhow!("{e}"))?, diff --git a/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs b/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs index a70d1c1..8c64d1f 100644 --- a/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs +++ b/seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs @@ -5,17 +5,19 @@ use seedelf_core::assets::Assets; use seedelf_core::constants::{Config, VARIANT, get_config}; #[tauri::command(async)] -pub async fn extract_seedelf(network_flag: bool, address: String, lovelace: u64) -> String { +pub async fn extract_seedelf( + network_flag: bool, + address: String, + lovelace: u64, + send_all: bool, +) -> String { let config: Config = match get_config(VARIANT, network_flag) { Some(c) => c, None => { return String::new(); } }; - let SweepSeedelfOutput { - tx_hash, - .. - } = match session::with_key(|sk| { + let SweepSeedelfOutput { tx_hash, .. } = match session::with_key(|sk| { build_sweep_seedelf( config, network_flag, @@ -24,6 +26,7 @@ pub async fn extract_seedelf(network_flag: bool, address: String, lovelace: u64) Assets::new(), None, *sk, + send_all, ) }) { Ok(v) => v.await, diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx index 6abcbdf..ee98b02 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx @@ -64,8 +64,8 @@ export function Extract() { // should be good to run the build tx function now try { setVariant("info"); - setMessage("Building Fund Seedelf Transaction"); - const _txHash = await extractSeedelf(network, address, lovelace); + setMessage("Building Extract Seedelf Transaction"); + const _txHash = await extractSeedelf(network, address, lovelace, isSendAll); if (_txHash) { setTxHash(_txHash); setShowExplorerLinkModal(true); @@ -164,7 +164,7 @@ export function Extract() { className={`rounded ${colorClasses.sky.bg} px-4 py-2 text-sm text-white disabled:opacity-50`} disabled={submitting || !address || !ada || !confirm} > - Send + Extract {(address.length != 0 || ada > 0) && ( diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/Send.tsx b/seedelf-platform/seedelf-gui/src/pages/Wallet/Send.tsx index 0634aab..a5a0a39 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/Send.tsx +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/Send.tsx @@ -73,7 +73,7 @@ export function Send() { // should be good to run the build tx function now try { setVariant("info"); - setMessage("Building Fund Seedelf Transaction"); + setMessage("Building Send Seedelf Transaction"); const _txHash = await sendSeedelf(network, seedelf, lovelace); if (_txHash) { setTxHash(_txHash); diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts b/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts index 73bdc9c..d42704e 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts @@ -61,11 +61,13 @@ export async function extractSeedelf( network: Network, address: string, lovelace: number, + sendAll: boolean, ): Promise { const flag = castNetwork(network); return await invoke("extract_seedelf", { networkFlag: flag, address: address, lovelace: lovelace, + sendAll: sendAll }); } \ No newline at end of file From 37d36bf1ce7771456d1e9636df8b9b0dc63e87f7 Mon Sep 17 00:00:00 2001 From: logicalmechanism Date: Sat, 9 Aug 2025 22:11:09 -0700 Subject: [PATCH 4/5] should be good for now --- seedelf-platform/seedelf-cli/src/commands/sweep.rs | 1 + .../seedelf-gui/src/pages/Wallet/Extract.tsx | 14 +++++++++++--- .../seedelf-gui/src/pages/Wallet/transactions.ts | 5 ++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/seedelf-platform/seedelf-cli/src/commands/sweep.rs b/seedelf-platform/seedelf-cli/src/commands/sweep.rs index 564437f..4cf0d44 100644 --- a/seedelf-platform/seedelf-cli/src/commands/sweep.rs +++ b/seedelf-platform/seedelf-cli/src/commands/sweep.rs @@ -284,6 +284,7 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<() Ok(()) } +#[allow(clippy::too_many_arguments)] pub async fn build_sweep_seedelf( config: Config, network_flag: bool, diff --git a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx index ee98b02..d6836b4 100644 --- a/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx +++ b/seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx @@ -34,7 +34,8 @@ export function Extract() { const [txHash, setTxHash] = useState(""); const [showConfirmationModal, setShowConfirmationModal] = useState(false); - const [showExplorerLinkModal, setShowExplorerLinkModal] = useState(false); + const [showExplorerLinkModal, setShowExplorerLinkModal] = + useState(false); const handleAddressValid = async (a: string) => { setVariant("error"); @@ -65,7 +66,12 @@ export function Extract() { try { setVariant("info"); setMessage("Building Extract Seedelf Transaction"); - const _txHash = await extractSeedelf(network, address, lovelace, isSendAll); + const _txHash = await extractSeedelf( + network, + address, + lovelace, + isSendAll, + ); if (_txHash) { setTxHash(_txHash); setShowExplorerLinkModal(true); @@ -81,7 +87,9 @@ export function Extract() { return (
-

Extract From A Seedelf

+

+ Extract From A Seedelf +

Date: Mon, 11 Aug 2025 10:35:32 -0700 Subject: [PATCH 5/5] ok to merge --- seedelf-platform/seedelf-gui/index.html | 32 ++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/seedelf-platform/seedelf-gui/index.html b/seedelf-platform/seedelf-gui/index.html index c27e18c..9f554b0 100644 --- a/seedelf-platform/seedelf-gui/index.html +++ b/seedelf-platform/seedelf-gui/index.html @@ -1,18 +1,22 @@ - - - - - - Seedelf - + + + + + + Seedelf + - -
- - - + +
+ + + + \ No newline at end of file