feat: Improve error handling and simplify async operations
This commit is contained in:
parent
ae687f17f5
commit
27e5a6df3e
@ -73,7 +73,7 @@ pub async fn send_eth(
|
||||
let tx = TransactionRequest::new()
|
||||
.to(to)
|
||||
.value(amount)
|
||||
.gas(21000);
|
||||
.gas(gas);
|
||||
|
||||
// Send the transaction
|
||||
let pending_tx = client.send_transaction(tx, None)
|
||||
@ -115,7 +115,7 @@ pub async fn send_eth_with_provider(
|
||||
let tx = TransactionRequest::new()
|
||||
.to(to)
|
||||
.value(amount)
|
||||
.gas(21000);
|
||||
.gas(gas);
|
||||
|
||||
// Send the transaction
|
||||
let pending_tx = client.send_transaction(tx, None)
|
||||
|
@ -3,8 +3,6 @@
|
||||
use rhai::{Engine, Dynamic, EvalAltResult};
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
use once_cell::sync::Lazy;
|
||||
use tokio::runtime::Runtime;
|
||||
@ -12,7 +10,7 @@ use ethers::types::{Address, U256};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::hero_vault::{keypair, symmetric, ethereum, kvs};
|
||||
use crate::hero_vault::kvs::{KVStore, DefaultStore};
|
||||
use crate::hero_vault::kvs::DefaultStore;
|
||||
use crate::hero_vault::ethereum::prepare_function_arguments;
|
||||
|
||||
// Global Tokio runtime for blocking async operations
|
||||
@ -20,6 +18,16 @@ static RUNTIME: Lazy<Mutex<Runtime>> = Lazy::new(|| {
|
||||
Mutex::new(Runtime::new().expect("Failed to create Tokio runtime"))
|
||||
});
|
||||
|
||||
// Helper function to run async operations and handle errors consistently
|
||||
fn run_async<F, T, E>(future: F) -> Result<T, String>
|
||||
where
|
||||
F: std::future::Future<Output = Result<T, E>>,
|
||||
E: std::fmt::Display,
|
||||
{
|
||||
let rt = RUNTIME.lock().map_err(|e| format!("Failed to acquire runtime lock: {}", e))?;
|
||||
rt.block_on(async { future.await.map_err(|e| e.to_string()) })
|
||||
}
|
||||
|
||||
// Get a platform-specific DefaultStore implementation for Rhai bindings
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn get_key_store() -> DefaultStore {
|
||||
@ -42,16 +50,16 @@ fn get_key_store() -> DefaultStore {
|
||||
fn get_key_store() -> DefaultStore {
|
||||
use once_cell::sync::Lazy;
|
||||
static STORE: Lazy<DefaultStore> = Lazy::new(|| {
|
||||
// In WASM we have to run this on the main thread the first time
|
||||
// This works because the cache in IndexedDbStore handles subsequent synchronous operations
|
||||
let rt = RUNTIME.lock().unwrap();
|
||||
rt.block_on(async {
|
||||
match kvs::open_default_store("rhai-vault", None).await {
|
||||
Ok(store) => store,
|
||||
Err(_) => kvs::create_default_store("rhai-vault", false, None).await
|
||||
.expect("Failed to create store")
|
||||
match run_async(async {
|
||||
kvs::open_default_store("rhai-vault", None).await
|
||||
.or_else(|_| kvs::create_default_store("rhai-vault", false, None).await)
|
||||
}) {
|
||||
Ok(store) => store,
|
||||
Err(e) => {
|
||||
log::error!("Failed to create key store: {}", e);
|
||||
panic!("Could not initialize key store: {}", e);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
STORE.clone()
|
||||
@ -76,26 +84,13 @@ fn auto_save_key_space(password: &str) -> bool {
|
||||
|
||||
// Export the current key space to a JSON string
|
||||
fn encrypt_key_space(password: &str) -> String {
|
||||
match keypair::get_current_space() {
|
||||
Ok(space) => {
|
||||
match symmetric::encrypt_key_space(&space, password) {
|
||||
Ok(encrypted_space) => {
|
||||
match symmetric::serialize_encrypted_space(&encrypted_space) {
|
||||
Ok(json) => json,
|
||||
Err(e) => {
|
||||
log::error!("Error serializing encrypted space: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Error encrypting key space: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
match keypair::get_current_space()
|
||||
.and_then(|space| symmetric::encrypt_key_space(&space, password))
|
||||
.and_then(|encrypted_space| symmetric::serialize_encrypted_space(&encrypted_space))
|
||||
{
|
||||
Ok(json) => json,
|
||||
Err(e) => {
|
||||
log::error!("Error getting current space: {}", e);
|
||||
log::error!("Error encrypting key space: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
@ -103,26 +98,13 @@ fn encrypt_key_space(password: &str) -> String {
|
||||
|
||||
// Import a key space from a JSON string
|
||||
fn decrypt_key_space(encrypted: &str, password: &str) -> bool {
|
||||
match symmetric::deserialize_encrypted_space(encrypted) {
|
||||
Ok(encrypted_space) => {
|
||||
match symmetric::decrypt_key_space(&encrypted_space, password) {
|
||||
Ok(space) => {
|
||||
match keypair::set_current_space(space) {
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::error!("Error setting current space: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Error decrypting key space: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
match symmetric::deserialize_encrypted_space(encrypted)
|
||||
.and_then(|encrypted_space| symmetric::decrypt_key_space(&encrypted_space, password))
|
||||
.and_then(|space| keypair::set_current_space(space))
|
||||
{
|
||||
Ok(_) => true,
|
||||
Err(e) => {
|
||||
log::error!("Error parsing encrypted space: {}", e);
|
||||
log::error!("Error decrypting key space: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -176,18 +158,14 @@ fn sign(message: &str) -> String {
|
||||
|
||||
fn verify(message: &str, signature: &str) -> bool {
|
||||
let message_bytes = message.as_bytes();
|
||||
match BASE64.decode(signature) {
|
||||
Ok(signature_bytes) => {
|
||||
match keypair::keypair_verify(message_bytes, &signature_bytes) {
|
||||
Ok(is_valid) => is_valid,
|
||||
Err(e) => {
|
||||
log::error!("Error verifying signature: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
match BASE64.decode(signature)
|
||||
.map_err(|e| e.to_string())
|
||||
.and_then(|sig_bytes| keypair::keypair_verify(message_bytes, &sig_bytes)
|
||||
.map_err(|e| e.to_string()))
|
||||
{
|
||||
Ok(is_valid) => is_valid,
|
||||
Err(e) => {
|
||||
log::error!("Error decoding signature: {}", e);
|
||||
log::error!("Error verifying signature: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -195,58 +173,44 @@ fn verify(message: &str, signature: &str) -> bool {
|
||||
|
||||
// Symmetric encryption
|
||||
fn generate_key() -> String {
|
||||
let key = symmetric::generate_symmetric_key();
|
||||
BASE64.encode(key)
|
||||
BASE64.encode(symmetric::generate_symmetric_key())
|
||||
}
|
||||
|
||||
fn encrypt(key: &str, message: &str) -> String {
|
||||
match BASE64.decode(key) {
|
||||
Ok(key_bytes) => {
|
||||
let message_bytes = message.as_bytes();
|
||||
match symmetric::encrypt_symmetric(&key_bytes, message_bytes) {
|
||||
Ok(ciphertext) => BASE64.encode(ciphertext),
|
||||
Err(e) => {
|
||||
log::error!("Error encrypting message: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
match BASE64.decode(key)
|
||||
.map_err(|e| format!("Error decoding key: {}", e))
|
||||
.and_then(|key_bytes| {
|
||||
symmetric::encrypt_symmetric(&key_bytes, message.as_bytes())
|
||||
.map_err(|e| format!("Error encrypting message: {}", e))
|
||||
})
|
||||
{
|
||||
Ok(ciphertext) => BASE64.encode(ciphertext),
|
||||
Err(e) => {
|
||||
log::error!("Error decoding key: {}", e);
|
||||
log::error!("{}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn decrypt(key: &str, ciphertext: &str) -> String {
|
||||
match BASE64.decode(key) {
|
||||
Ok(key_bytes) => {
|
||||
match BASE64.decode(ciphertext) {
|
||||
Ok(ciphertext_bytes) => {
|
||||
match symmetric::decrypt_symmetric(&key_bytes, &ciphertext_bytes) {
|
||||
Ok(plaintext) => {
|
||||
match String::from_utf8(plaintext) {
|
||||
Ok(text) => text,
|
||||
Err(e) => {
|
||||
log::error!("Error converting plaintext to string: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Error decrypting ciphertext: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Error decoding ciphertext: {}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
},
|
||||
match BASE64.decode(key)
|
||||
.map_err(|e| format!("Error decoding key: {}", e))
|
||||
.and_then(|key_bytes| {
|
||||
BASE64.decode(ciphertext)
|
||||
.map_err(|e| format!("Error decoding ciphertext: {}", e))
|
||||
.and_then(|cipher_bytes| {
|
||||
symmetric::decrypt_symmetric(&key_bytes, &cipher_bytes)
|
||||
.map_err(|e| format!("Error decrypting ciphertext: {}", e))
|
||||
})
|
||||
})
|
||||
.and_then(|plaintext| {
|
||||
String::from_utf8(plaintext)
|
||||
.map_err(|e| format!("Error converting plaintext to string: {}", e))
|
||||
})
|
||||
{
|
||||
Ok(text) => text,
|
||||
Err(e) => {
|
||||
log::error!("Error decoding key: {}", e);
|
||||
log::error!("{}", e);
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
@ -374,15 +338,6 @@ fn get_network_explorer_url(network_name: &str) -> String {
|
||||
|
||||
// Get the balance of an address on a specific network
|
||||
fn get_balance(network_name: &str, address: &str) -> String {
|
||||
// Get the runtime
|
||||
let rt = match RUNTIME.lock() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
log::error!("Failed to acquire runtime lock: {}", e);
|
||||
return String::new();
|
||||
}
|
||||
};
|
||||
|
||||
// Parse the address
|
||||
let addr = match Address::from_str(address) {
|
||||
Ok(addr) => addr,
|
||||
@ -393,9 +348,7 @@ fn get_balance(network_name: &str, address: &str) -> String {
|
||||
};
|
||||
|
||||
// Execute the balance query in a blocking manner
|
||||
match rt.block_on(async {
|
||||
ethereum::get_balance(network_name, addr).await
|
||||
}) {
|
||||
match run_async(ethereum::get_balance(network_name, addr)) {
|
||||
Ok(balance) => {
|
||||
// Format the balance with the network's token symbol
|
||||
match ethereum::get_network_by_name(network_name) {
|
||||
@ -412,15 +365,6 @@ fn get_balance(network_name: &str, address: &str) -> String {
|
||||
|
||||
// Send ETH from one address to another
|
||||
fn send_eth(network_name: &str, to_address: &str, amount_str: &str) -> String {
|
||||
// Get the runtime
|
||||
let rt = match RUNTIME.lock() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
log::error!("Failed to acquire runtime lock: {}", e);
|
||||
return String::new();
|
||||
}
|
||||
};
|
||||
|
||||
// Parse the address
|
||||
let to_addr = match Address::from_str(to_address) {
|
||||
Ok(addr) => addr,
|
||||
@ -449,9 +393,7 @@ fn send_eth(network_name: &str, to_address: &str, amount_str: &str) -> String {
|
||||
};
|
||||
|
||||
// Execute the transaction in a blocking manner
|
||||
match rt.block_on(async {
|
||||
ethereum::send_eth(&wallet, network_name, to_addr, amount).await
|
||||
}) {
|
||||
match run_async(ethereum::send_eth(&wallet, network_name, to_addr, amount)) {
|
||||
Ok(tx_hash) => format!("{:?}", tx_hash),
|
||||
Err(e) => {
|
||||
log::error!("Transaction failed: {}", e);
|
||||
@ -538,15 +480,6 @@ fn call_contract_read(contract_json: &str, function_name: &str, args: rhai::Arra
|
||||
}
|
||||
};
|
||||
|
||||
// Get the runtime
|
||||
let rt = match RUNTIME.lock() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
log::error!("Failed to acquire runtime lock: {}", e);
|
||||
return Dynamic::UNIT;
|
||||
}
|
||||
};
|
||||
|
||||
// Create a provider
|
||||
let provider = match ethereum::create_provider(&contract.network.name) {
|
||||
Ok(p) => p,
|
||||
@ -557,9 +490,7 @@ fn call_contract_read(contract_json: &str, function_name: &str, args: rhai::Arra
|
||||
};
|
||||
|
||||
// Execute the call in a blocking manner
|
||||
match rt.block_on(async {
|
||||
ethereum::call_read_function(&contract, &provider, function_name, tokens).await
|
||||
}) {
|
||||
match run_async(ethereum::call_read_function(&contract, &provider, function_name, tokens)) {
|
||||
Ok(result) => ethereum::token_to_dynamic(&result),
|
||||
Err(e) => {
|
||||
log::error!("Failed to call contract function: {}", e);
|
||||
@ -593,15 +524,6 @@ fn call_contract_write(contract_json: &str, function_name: &str, args: rhai::Arr
|
||||
}
|
||||
};
|
||||
|
||||
// Get the runtime
|
||||
let rt = match RUNTIME.lock() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
log::error!("Failed to acquire runtime lock: {}", e);
|
||||
return String::new();
|
||||
}
|
||||
};
|
||||
|
||||
// Get the wallet
|
||||
let wallet = match ethereum::get_current_ethereum_wallet() {
|
||||
Ok(w) => w,
|
||||
@ -621,9 +543,7 @@ fn call_contract_write(contract_json: &str, function_name: &str, args: rhai::Arr
|
||||
};
|
||||
|
||||
// Execute the transaction in a blocking manner
|
||||
match rt.block_on(async {
|
||||
ethereum::call_write_function(&contract, &wallet, &provider, function_name, tokens).await
|
||||
}) {
|
||||
match run_async(ethereum::call_write_function(&contract, &wallet, &provider, function_name, tokens)) {
|
||||
Ok(tx_hash) => format!("{:?}", tx_hash),
|
||||
Err(e) => {
|
||||
// Log the error details for debugging
|
||||
@ -657,20 +577,20 @@ fn get_agung_address() -> String {
|
||||
get_ethereum_address()
|
||||
}
|
||||
|
||||
fn create_wallet_for_network(network_name: &str) -> bool {
|
||||
fn create_wallet_for_network(_network_name: &str) -> bool {
|
||||
create_ethereum_wallet()
|
||||
}
|
||||
|
||||
fn get_wallet_address_for_network(network_name: &str) -> String {
|
||||
fn get_wallet_address_for_network(_network_name: &str) -> String {
|
||||
get_ethereum_address()
|
||||
}
|
||||
|
||||
fn clear_wallets_for_network(network_name: &str) -> bool {
|
||||
fn clear_wallets_for_network(_network_name: &str) -> bool {
|
||||
ethereum::clear_ethereum_wallets();
|
||||
true
|
||||
}
|
||||
|
||||
fn create_wallet_from_private_key_for_network(private_key: &str, network_name: &str) -> bool {
|
||||
fn create_wallet_from_private_key_for_network(private_key: &str, _network_name: &str) -> bool {
|
||||
create_ethereum_wallet_from_private_key(private_key)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user