Skip to content
Open
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "carpe"
version = "1.0.5"
version = "1.1.1"
authors = ["0LNetworkCommunity"]
default-run = "carpe"
description = "a wallet for OpenLibra"
Expand Down
147 changes: 113 additions & 34 deletions src-tauri/src/commands/tx.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,87 @@
//! transaction scripts
use std::str::FromStr;

use crate::key_manager::{get_private_key, inject_private_key_to_cfg};
use crate::key_manager::get_private_key;
use crate::{carpe_error::CarpeError, configs::get_cfg};

use libra_txs::submit_transaction::Sender;
use libra_types::exports::ChainId;
use libra_types::exports::{AccountAddress, AccountKey};

fn make_account_key(address: &AccountAddress) -> anyhow::Result<AccountKey> {
let pk = get_private_key(address)?;
Ok(AccountKey::from_private_key(pk))
}

/// Creates a new Sender with proper handling of legacy addresses.
/// This function centralizes the logic for creating a transaction sender
/// with proper chain ID and legacy address support.
async fn create_sender_with_legacy(
sender_address: AccountAddress,
legacy: bool,
) -> Result<
(
libra_txs::submit_transaction::Sender,
libra_types::core_types::app_cfg::AppCfg,
),
CarpeError,
> {
// Get configuration
let config = get_cfg()?;

// Get private key for the sender
let pk = get_private_key(&sender_address)?;
let account_key = AccountKey::from_private_key(pk);

// Get URL from config
let url = config.pick_url(None)?;

// Create the client
let client = libra_types::exports::Client::new(url.clone());

// Get chain ID from the live network with fallback to config
println!("Fetching current chain ID from network...");
let chain_id = match client.get_index().await {
Ok(metadata) => {
let chain_id_value = metadata.into_inner().chain_id;
println!("Network chain ID: {}", chain_id_value);
ChainId::new(chain_id_value)
}
Err(e) => {
println!(
"Warning: Failed to get chain ID from network: {}. Using default from config.",
e
);
// Fallback to config chain ID
let config_chain_id = config.workspace.default_chain_id.id();
println!("Using config chain ID: {}", config_chain_id);
ChainId::new(config_chain_id)
}
};

// Initialize the sender with the legacy flag
let mut sender = libra_txs::submit_transaction::Sender::new(
account_key,
chain_id,
Some(client),
legacy, // Pass the legacy flag here
)
.await?;

// Set the transaction cost
let tx_cost = config.tx_configs.get_cost(None);
sender.set_tx_cost(&tx_cost);

Ok((sender, config))
}

#[tauri::command(async)]
pub async fn coin_transfer(
_sender: AccountAddress,
receiver: &str,
amount: u64,
_legacy: bool,
legacy: bool,
) -> Result<(), CarpeError> {
// NOTE: unsure Serde was catching all cases check serialization
// Parse receiver address, add 0x prefix if needed
let receiver_account = match AccountAddress::from_str(receiver) {
Ok(a) => a,
Err(e) => {
Expand All @@ -29,17 +91,36 @@ pub async fn coin_transfer(
}
};

let mut config = get_cfg()?;
inject_private_key_to_cfg(&mut config, _sender)?;
let mut sender = Sender::from_app_cfg(&config, Some(_sender.to_string())).await?;
sender
// Use the common function to create a sender with legacy address support
let (mut sender, _) = create_sender_with_legacy(_sender, legacy).await?;

println!(
"Attempting transfer from {} to {} of {} coins",
_sender, receiver_account, amount
);

// Use the transfer method - the last parameter is 'estimate_only'
match sender
.transfer(receiver_account, amount as f64, false)
.await?;
Ok(())
.await
{
Ok(_) => {
println!("Transaction completed successfully");
Ok(())
}
Err(e) => {
println!("Transaction failed: {}", e);
Err(CarpeError::misc(&format!("Transaction failed: {}", e)))
}
}
}

#[tauri::command(async)]
pub async fn vouch_transaction(_sender: AccountAddress, receiver: &str) -> Result<(), CarpeError> {
pub async fn vouch_transaction(
_sender: AccountAddress,
receiver: &str,
legacy: bool,
) -> Result<(), CarpeError> {
let receiver_account = match AccountAddress::from_str(receiver) {
Ok(a) => a,
Err(e) => {
Expand All @@ -51,16 +132,18 @@ pub async fn vouch_transaction(_sender: AccountAddress, receiver: &str) -> Resul
}
};

let mut config = get_cfg()?;
inject_private_key_to_cfg(&mut config, _sender)?;
// Use the common function to create a sender with legacy address support
let (mut sender, _) = create_sender_with_legacy(_sender, legacy).await?;

let mut sender = Sender::from_app_cfg(&config, Some(_sender.to_string())).await?;

// Try the revoke vouch function path
// Function path for vouching
let function_path = "0x1::vouch_txs::vouch_for";

// Format address as a Move address literal (with 0x prefix)
let formatted_address = format!("0x{}", receiver_account.to_hex());
println!(
"Calling {} with argument: {}",
function_path, formatted_address
);

match sender
.generic(
Expand All @@ -72,24 +155,22 @@ pub async fn vouch_transaction(_sender: AccountAddress, receiver: &str) -> Resul
{
Ok(_) => {
println!("Successfully called {}", function_path);
return Ok(());
Ok(())
}
Err(e) => {
println!("Failed to call {}: {}", function_path, e);
Err(CarpeError::misc(&format!(
"Failed to call vouch function: {}",
e
)))
}
}
// If we get here, all attempts failed
Err(CarpeError::misc(
"Failed to call vouch function with any known path or argument format",
))
}

#[tauri::command(async)]
pub async fn rejoin_transaction(_sender: AccountAddress) -> Result<(), CarpeError> {
let mut config = get_cfg()?;
inject_private_key_to_cfg(&mut config, _sender)?;

let mut sender = Sender::from_app_cfg(&config, Some(_sender.to_string())).await?;
pub async fn rejoin_transaction(_sender: AccountAddress, legacy: bool) -> Result<(), CarpeError> {
// Use the common function to create a sender with legacy address support
let (mut sender, _) = create_sender_with_legacy(_sender, legacy).await?;

match sender
.generic(
Expand All @@ -112,6 +193,7 @@ pub async fn rejoin_transaction(_sender: AccountAddress) -> Result<(), CarpeErro
pub async fn revoke_vouch_transaction(
_sender: AccountAddress,
receiver: &str,
legacy: bool,
) -> Result<(), CarpeError> {
let receiver_account = match AccountAddress::from_str(receiver) {
Ok(a) => a,
Expand All @@ -124,10 +206,8 @@ pub async fn revoke_vouch_transaction(
}
};

let mut config = get_cfg()?;
inject_private_key_to_cfg(&mut config, _sender)?;

let mut sender = Sender::from_app_cfg(&config, Some(_sender.to_string())).await?;
// Use the common function to create a sender with legacy address support
let (mut sender, _) = create_sender_with_legacy(_sender, legacy).await?;

// Try the revoke vouch function path
let function_path = "0x1::vouch_txs::revoke";
Expand Down Expand Up @@ -158,6 +238,7 @@ pub async fn revoke_vouch_transaction(
pub async fn cw_reauth_transaction(
_sender: AccountAddress,
wallet_address: &str,
legacy: bool,
) -> Result<(), CarpeError> {
// Parse the wallet address
let wallet_account = match AccountAddress::from_str(wallet_address) {
Expand All @@ -171,10 +252,8 @@ pub async fn cw_reauth_transaction(
}
};

let mut config = get_cfg()?;
inject_private_key_to_cfg(&mut config, _sender)?;

let mut sender = Sender::from_app_cfg(&config, Some(_sender.to_string())).await?;
// Use the common function to create a sender with legacy address support
let (mut sender, _) = create_sender_with_legacy(_sender, legacy).await?;

// Try the community wallet reauthorization function path
let function_path = "0x1::donor_voice_txs::vote_reauth_tx";
Expand Down
3 changes: 2 additions & 1 deletion src/components/txs/CwReauthForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@

await invoke("cw_reauth_transaction", {
sender: account.account,
walletAddress: selectedWallet // Pass the selected wallet address to reauthorize
walletAddress: selectedWallet, // Pass the selected wallet address to reauthorize
legacy: account.account.startsWith('0'.repeat(32)) // Use same legacy detection as other forms
})

notify_success($_('txs.cwreauth.success'))
Expand Down
3 changes: 2 additions & 1 deletion src/components/txs/RevokeForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@

await invoke("revoke_vouch_transaction", {
sender: account.account,
receiver: receiver
receiver: receiver,
legacy: account.account.startsWith('0'.repeat(32)) // Use same legacy detection as in other forms
})

notify_success($_('txs.revoke.success'))
Expand Down
2 changes: 1 addition & 1 deletion src/components/txs/VouchForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
await invoke("vouch_transaction", {
sender: account.account,
receiver: receiver,
legacy: false
legacy: account.account.startsWith('0'.repeat(32)) // Use same legacy detection as in Transactions
})

notify_success($_('txs.vouch.success'))
Expand Down
7 changes: 5 additions & 2 deletions src/components/wallet/MigrationStatus.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@
// Show loading state while processing
isLoading = true;

// Call the rejoin_transaction Tauri function directly
await invoke('rejoin_transaction', { sender: account });
// Call the rejoin_transaction Tauri function directly with legacy flag
await invoke('rejoin_transaction', {
sender: account,
legacy: account.startsWith('0'.repeat(32)) // Use same legacy detection as other transactions
});

// Refresh status checks after successful rejoin
await checkMigrationStatus();
Expand Down
Loading