#![allow(deprecated)]
use crate::actions::NetworkContext;
use crate::args::max_fee_per_gas::{MaxFeePerGasParam, get_max_fee_per_gas_from_opt_param};
use crate::wallet::load_wallet;
use autonomi::client::register::RegisterAddress;
use autonomi::client::register::SecretKey as RegisterSecretKey;
use autonomi::{Client, TransactionConfig};
use color_eyre::Section;
use color_eyre::eyre::Context;
use color_eyre::eyre::Result;
use color_eyre::eyre::eyre;
pub fn generate_key(overwrite: bool) -> Result<()> {
let key_path = crate::keys::get_register_signing_key_path()?;
if key_path.exists() && !overwrite {
error!("Register key already exists at: {key_path:?}");
return Err(eyre!("Register key already exists at: {}", key_path.display()))
.with_suggestion(|| "if you want to overwrite the existing key, run the command with the --overwrite flag")
.with_warning(|| "overwriting the existing key might result in loss of access to any existing registers created using that key");
}
let key = RegisterSecretKey::random();
let path = crate::keys::create_register_signing_key_file(key)
.wrap_err("Failed to create new register key")?;
info!("Created new register key at: {path:?}");
println!("✅ Created new register key at: {}", path.display());
Ok(())
}
pub async fn cost(name: &str, network_context: NetworkContext) -> Result<()> {
let main_registers_key = crate::keys::get_register_signing_key()
.wrap_err("The register key is required to perform this action")?;
let client = crate::actions::connect_to_network(network_context)
.await
.map_err(|(err, _)| err)?;
let key_for_name = Client::register_key_from_name(&main_registers_key, name);
let cost = client
.register_cost(&key_for_name.public_key())
.await
.wrap_err("Failed to get cost for register")?;
info!("Estimated cost to create a register with name {name}: {cost}");
println!("✅ The estimated cost to create a register with name {name} is: {cost}");
Ok(())
}
pub async fn create(
name: &str,
value: &str,
hex: bool,
network_context: NetworkContext,
max_fee_per_gas_param: Option<MaxFeePerGasParam>,
) -> Result<()> {
let main_registers_key = crate::keys::get_register_signing_key()
.wrap_err("The register key is required to perform this action")?;
let client = crate::actions::connect_to_network(network_context)
.await
.map_err(|(err, _)| err)?;
let mut wallet = load_wallet(client.evm_network())?;
let max_fee_per_gas =
get_max_fee_per_gas_from_opt_param(max_fee_per_gas_param, client.evm_network())?;
wallet.set_transaction_config(TransactionConfig { max_fee_per_gas });
let register_key = Client::register_key_from_name(&main_registers_key, name);
println!("Creating register with name: {name}");
info!("Creating register with name: {name}");
let value_bytes = if hex {
hex::decode(value.trim_start_matches("0x"))
.wrap_err("Failed to decode hex value")
.with_suggestion(|| "Make sure the value is a valid hex string")?
} else {
value.as_bytes().to_vec()
};
let content = Client::register_value_from_bytes(&value_bytes)?;
let (cost, address) = client
.register_create(®ister_key, content, wallet.into())
.await
.wrap_err("Failed to create register")?;
println!("✅ Register created at address: {address}");
println!("With name: {name}");
if hex {
println!("And initial hex value: [{}]", hex::encode(&value_bytes));
} else {
println!("And initial value: [{value}]");
}
info!("Register created at address: {address} with name: {name}");
println!("Total cost: {cost} AttoTokens");
crate::user_data::write_local_register(&address, name)
.wrap_err("Failed to save register to local user data")
.with_suggestion(|| "Local user data saves the register address above to disk (for the register list command), without it you need to keep track of the address yourself")?;
info!("Saved register to local user data");
Ok(())
}
pub async fn edit(
address: String,
name: bool,
value: &str,
hex: bool,
network_context: NetworkContext,
max_fee_per_gas_param: Option<MaxFeePerGasParam>,
) -> Result<()> {
let main_registers_key = crate::keys::get_register_signing_key()
.wrap_err("The register key is required to perform this action")?;
let client = crate::actions::connect_to_network(network_context)
.await
.map_err(|(err, _)| err)?;
let mut wallet = load_wallet(client.evm_network())?;
let max_fee_per_gas =
get_max_fee_per_gas_from_opt_param(max_fee_per_gas_param, client.evm_network())?;
wallet.set_transaction_config(TransactionConfig { max_fee_per_gas });
let value_bytes = if hex {
hex::decode(value.trim_start_matches("0x"))
.wrap_err("Failed to decode hex value")
.with_suggestion(|| "Make sure the value is a valid hex string")?
} else {
value.as_bytes().to_vec()
};
let value_bytes = Client::register_value_from_bytes(&value_bytes)?;
let register_key = if name {
let name_str = address.clone();
Client::register_key_from_name(&main_registers_key, &name_str)
} else {
let addr = RegisterAddress::from_hex(&address)
.wrap_err(format!("Failed to parse register address: {address}"))
.with_suggestion(|| {
"if you want to use the name as the address, run the command with the --name flag"
})?;
let name_str = crate::user_data::get_name_of_local_register_with_address(&addr)
.wrap_err(format!("Could not find a register with address in local user data: {address}"))
.with_suggestion(|| "This register is not known to this client, try to create it first.")
.with_suggestion(|| "If you indeed have created this register before, retry using its name by using the --name flag")?;
Client::register_key_from_name(&main_registers_key, &name_str)
};
println!("Attempting to update register at {address} with new value: {value}");
info!("Attempting to update register at {address} with new value: {value}");
let cost = client
.register_update(®ister_key, value_bytes, wallet.into())
.await
.wrap_err(format!("Failed to update register at address: {address}"))?;
println!("✅ Successfully updated register");
println!("With value: [{value}]");
println!("Total cost: {cost} AttoTokens");
info!("Successfully updated register at address: {address}");
if name {
let addr = RegisterAddress::new(register_key.public_key());
crate::user_data::write_local_register(&addr, &address)
.wrap_err("Failed to save register to local user data")
.with_suggestion(|| "Local user data saves the register address above to disk (for the register list command), without it you need to keep track of the address yourself")?;
info!("Saved register to local user data");
}
Ok(())
}
pub async fn get(
address: String,
name: bool,
hex: bool,
network_context: NetworkContext,
) -> Result<()> {
let client = crate::actions::connect_to_network(network_context)
.await
.map_err(|(err, _)| err)?;
let addr = if name {
let name_str = address.clone();
let main_registers_key = crate::keys::get_register_signing_key()
.wrap_err("The register key is required to perform this action")?;
let register_key = Client::register_key_from_name(&main_registers_key, &name_str);
RegisterAddress::new(register_key.public_key())
} else {
RegisterAddress::from_hex(&address)
.wrap_err(format!("Failed to parse register address: {address}"))
.with_suggestion(|| {
"if you want to use the name as the address, run the command with the --name flag"
})?
};
if name {
println!("Getting register with name: {address}");
info!("Getting register with name: {address}");
} else {
println!("Getting register at address: {address}");
info!("Getting register at address: {address}");
}
let value_bytes = client
.register_get(&addr)
.await
.wrap_err(format!("Error getting register at: {address}"))?;
println!("✅ Register found at: {address}");
info!("Register found at: {address}");
if hex {
let hex_value = hex::encode(value_bytes);
println!("With hex value: [{hex_value}]");
info!("With hex value: [{hex_value}]");
} else {
let value = String::from_utf8_lossy(&value_bytes);
println!("With value: [{value}]");
info!("With value: [{value}]");
}
if name {
crate::user_data::write_local_register(&addr, &address)
.wrap_err("Failed to save register to local user data")
.with_suggestion(|| "Local user data saves the register address above to disk (for the register list command), without it you need to keep track of the address yourself")?;
info!("Saved register to local user data");
}
Ok(())
}
pub fn list() -> Result<()> {
println!("Retrieving local user data...");
let registers = crate::user_data::get_local_registers()?;
println!("✅ You have {} register(s):", registers.len());
for (addr, name) in registers {
println!("{}: {}", name, addr.to_hex());
}
Ok(())
}
pub async fn history(
address: String,
name: bool,
hex: bool,
network_context: NetworkContext,
) -> Result<()> {
let client = crate::actions::connect_to_network(network_context)
.await
.map_err(|(err, _)| err)?;
let addr = if name {
let name_str = address.clone();
let main_registers_key = crate::keys::get_register_signing_key()
.wrap_err("The register key is required to perform this action")?;
let register_key = Client::register_key_from_name(&main_registers_key, &name_str);
RegisterAddress::new(register_key.public_key())
} else {
RegisterAddress::from_hex(&address)
.wrap_err(format!("Failed to parse register address: {address}"))
.with_suggestion(|| {
"if you want to use the name as the address, run the command with the --name flag"
})?
};
if name {
println!("Getting register history with name: {address}");
info!("Getting register history with name: {address}");
} else {
println!("Getting register history at address: {address}");
info!("Getting register history at address: {address}");
}
let mut history = client.register_history(&addr);
println!("✅ Register history found at: {address}");
info!("Register history found at: {address}");
println!("History of values:");
let values = history
.collect()
.await
.wrap_err(format!("Error getting register history at: {address}"))?;
for value in values {
if hex {
let hex_value = hex::encode(value);
println!("[{hex_value}]");
} else {
let value_str = String::from_utf8_lossy(&value[..]);
println!("[{value_str}]");
}
}
Ok(())
}