use crate::encoding::{classify_recipient, parse_token_amount, short_addr, tx_short_hash, Recipient};
use crate::app::{dom, templates};
pub(super) async fn refresh_tba_panel() {
if dom::by_id("tba-act-address").is_none() {
return;
}
let Some(name) = crate::app::tenant::current_name() else { return };
let tba = crate::app::net::read(crate::app::registry::tba_of_name(&name))
.await
.ok()
.and_then(Result::ok)
.flatten();
let Some(tba) = tba else {
dom::swap_inner("tba-act-address", "—");
dom::swap_inner("tba-act-balance", "—");
return;
};
dom::swap_inner("tba-act-address", &maud::html! { (tba) }.into_string());
let balance = crate::app::net::read(crate::app::registry::token_balance_of(&tba))
.await
.ok()
.and_then(Result::ok);
match balance {
Some(wei) => dom::swap_inner(
"tba-act-balance",
&format!("{} LH", crate::app::format_wei_as_test_eth(wei)),
),
None => dom::swap_inner("tba-act-balance", "—"),
}
}
pub(super) fn tba_send_pressed() {
let recipient_raw = dom::input_by_id("tba-send-recipient")
.map(|i| i.value())
.unwrap_or_default();
let amount_raw = dom::input_by_id("tba-send-amount")
.map(|i| i.value())
.unwrap_or_default();
if recipient_raw.trim().is_empty() {
return;
}
let Some(amount_wei) = parse_token_amount(&amount_raw) else { return };
if amount_wei == 0 {
return;
}
let recipient = match classify_recipient(&recipient_raw) {
Ok(r) => r,
Err(e) => {
dom::swap_inner("tba-send-msg", &dom::msg_span(dom::Msg::Error, &e));
return;
}
};
dom::swap_inner("tba-send-msg", "");
wasm_bindgen_futures::spawn_local(async move {
let resolved = match &recipient {
Recipient::Address(addr) => Ok(addr.clone()),
Recipient::Name(name) => {
match crate::app::registry::tba_of_name(name).await {
Ok(Some(tba)) => Ok(tba),
Ok(None) => Err(format!("\"{name}\" is not a registered name")),
Err(e) => Err(format!("lookup failed: {e}")),
}
}
};
match resolved {
Ok(to_hex) => {
let label = match &recipient {
Recipient::Address(_) => short_addr(&to_hex),
Recipient::Name(name) => format!("{name} ({})", short_addr(&to_hex)),
};
dom::remember_focus();
dom::swap_inner(
"tba-send-confirm-slot",
&templates::tba_send_confirm_panel(&label, &to_hex, amount_wei)
.into_string(),
);
dom::focus_first_in("tba-send-confirm-panel");
}
Err(e) => {
dom::swap_inner("tba-send-msg", &dom::msg_span(dom::Msg::Error, &e));
}
}
});
}
pub(super) fn tba_send_cancel_pressed() {
dom::swap_inner("tba-send-confirm-slot", "");
dom::swap_inner("tba-send-msg", "");
dom::restore_focus();
}
pub(super) fn tba_send_confirm_pressed(arg: String) {
let Some((to_hex, amount_str)) = arg.split_once(':') else { return };
let Ok(amount_wei) = amount_str.parse::<u128>() else { return };
if amount_wei == 0 {
return;
}
let typed = dom::input_by_id("tba-send-confirm-input")
.map(|i| i.value())
.unwrap_or_default();
if typed.trim().is_empty() || parse_token_amount(&typed) != Some(amount_wei) {
dom::swap_inner(
"tba-send-msg",
&dom::msg_span(dom::Msg::Error, "type the amount to confirm"),
);
return;
}
let to_hex = to_hex.to_string();
dom::swap_inner("tba-send-msg", &dom::msg_span(dom::Msg::Accent, "sending…"));
wasm_bindgen_futures::spawn_local(async move {
match run_tba_send(&to_hex, amount_wei).await {
Ok(tx_hash) => {
dom::swap_inner("tba-send-confirm-slot", "");
dom::restore_focus();
if let Some(input) = dom::input_by_id("tba-send-recipient") {
input.set_value("");
}
if let Some(input) = dom::input_by_id("tba-send-amount") {
input.set_value("");
}
dom::swap_inner(
"tba-send-msg",
&dom::msg_span(
dom::Msg::Muted,
&format!("sent — tx {}", tx_short_hash(&tx_hash)),
),
);
refresh_tba_panel().await;
}
Err(e) => {
dom::swap_inner(
"tba-send-msg",
&dom::msg_span(dom::Msg::Error, &format!("send failed: {e}")),
);
}
}
});
}
async fn run_tba_send(to_hex: &str, amount_wei: u128) -> Result<String, String> {
let (name, owner) = crate::app::tenant::current_tenant_owner().await?;
let token_id = crate::app::registry::id_of_name(&name)
.await
.map_err(|e| format!("id: {e}"))?;
if token_id == 0 {
return Err("name not registered".into());
}
let tba = crate::app::registry::tba_of_name(&name)
.await
.map_err(|e| format!("tba: {e}"))?
.ok_or_else(|| "no agent wallet for this name".to_string())?;
let balance = crate::app::registry::token_balance_of(&tba)
.await
.map_err(|e| format!("balance: {e}"))?;
if balance < amount_wei {
return Err(format!(
"agent wallet holds {} $LH",
crate::app::format_wei_as_test_eth(balance)
));
}
let calls = crate::app::registry::tba_send_lh_calls(token_id, &tba, to_hex, amount_wei)?;
let purpose = format!(
"send {} $LH from {name}'s agent wallet",
crate::app::format_wei_as_test_eth(amount_wei)
);
crate::app::events::run_sponsored_tempo_call(
&owner,
calls,
crate::app::registry::TBA_SEND_LH_GAS,
&purpose,
)
.await
}