use std::str::FromStr;
use std::sync::Arc;
use phoenix_rise::PhoenixHttpClient;
use solana_keypair::Keypair;
use solana_signer::Signer;
use tokio::sync::mpsc::UnboundedSender;
use tracing::warn;
use super::super::super::constants::MAX_REFERRAL_CODE_LEN;
use super::super::super::state::TxStatusMsg;
use super::*;
const COSMIC_REFERRAL_CODE: &str = "COSMIC";
const CHOICE_COUNT: usize = 3;
const CHOICE_COSMIC: usize = 0;
const CHOICE_CUSTOM: usize = 1;
const _CHOICE_SKIP: usize = 2;
pub(in crate::tui::runtime) fn handle_choosing_referral(
code: KeyCode,
state: &mut TuiState,
channels: &Channels,
http: Arc<PhoenixHttpClient>,
) -> KeyAction {
let s = strings();
match code {
KeyCode::Up => {
if state.trading.referral_choice_index > 0 {
state.trading.referral_choice_index -= 1;
} else {
state.trading.referral_choice_index = CHOICE_COUNT - 1;
}
KeyAction::Redraw
}
KeyCode::Down | KeyCode::Tab => {
state.trading.referral_choice_index =
(state.trading.referral_choice_index + 1) % CHOICE_COUNT;
KeyAction::Redraw
}
KeyCode::Enter => match state.trading.referral_choice_index {
CHOICE_COSMIC => {
let Some(kp) = state.trading.keypair.as_ref().cloned() else {
state.trading.input_mode = InputMode::Normal;
return KeyAction::Redraw;
};
spawn_referral_activation(
http,
kp,
COSMIC_REFERRAL_CODE.to_string(),
s.tx_registered_referral.to_string(),
channels.tx_status.clone(),
);
state.trading.set_status_title(s.tx_registering_referral);
state.trading.input_mode = InputMode::Normal;
KeyAction::Redraw
}
CHOICE_CUSTOM => {
state.trading.referral_code_buffer.clear();
state.trading.referral_code_error = None;
state.trading.input_mode = InputMode::EditingReferralCode;
KeyAction::Redraw
}
_ => {
close_with_connected_status(state);
KeyAction::Redraw
}
},
KeyCode::Esc => {
close_with_connected_status(state);
KeyAction::Redraw
}
_ => KeyAction::Nothing,
}
}
pub(in crate::tui::runtime) fn handle_editing_referral_code(
code: KeyCode,
state: &mut TuiState,
channels: &Channels,
http: Arc<PhoenixHttpClient>,
) -> KeyAction {
let s = strings();
match code {
KeyCode::Enter => {
let trimmed = state.trading.referral_code_buffer.trim().to_string();
if trimmed.is_empty() {
state.trading.referral_code_buffer.clear();
state.trading.referral_code_error = None;
close_with_connected_status(state);
return KeyAction::Redraw;
}
let Some(kp) = state.trading.keypair.as_ref().cloned() else {
state.trading.referral_code_error = Some("wallet not loaded".to_string());
return KeyAction::Redraw;
};
let success_title = format!("{} {}", s.tx_registered_custom_prefix, trimmed);
spawn_referral_activation(
http,
kp,
trimmed.clone(),
success_title,
channels.tx_status.clone(),
);
state
.trading
.set_status_title(format!("{} {}…", s.tx_registering_custom_prefix, trimmed));
state.trading.input_mode = InputMode::Normal;
state.trading.referral_code_buffer.clear();
state.trading.referral_code_error = None;
KeyAction::Redraw
}
KeyCode::Esc => {
state.trading.referral_code_buffer.clear();
state.trading.referral_code_error = None;
close_with_connected_status(state);
KeyAction::Redraw
}
KeyCode::Backspace => {
state.trading.referral_code_buffer.pop();
state.trading.referral_code_error = None;
KeyAction::Redraw
}
KeyCode::Char(c) if !c.is_control() && !c.is_whitespace() => {
if state.trading.referral_code_buffer.chars().count() >= MAX_REFERRAL_CODE_LEN {
return KeyAction::Nothing;
}
state.trading.referral_code_buffer.push(c);
state.trading.referral_code_error = None;
KeyAction::Redraw
}
_ => KeyAction::Nothing,
}
}
fn close_with_connected_status(state: &mut TuiState) {
state.trading.input_mode = InputMode::Normal;
let s = strings();
let pk = state.trading.wallet_label.clone();
if pk.is_empty() {
state.trading.set_status_title(s.st_wallet_connected);
} else {
state
.trading
.set_status_title(format!("{} {}", s.st_wallet_connected_as, pk));
}
}
fn spawn_referral_activation(
http: Arc<PhoenixHttpClient>,
kp: Arc<Keypair>,
referral_code: String,
success_title: String,
tx_status: UnboundedSender<TxStatusMsg>,
) {
tokio::spawn(async move {
let s = strings();
let authority = match solana_pubkey::Pubkey::from_str(&kp.pubkey().to_string()) {
Ok(pk) => pk,
Err(e) => {
warn!(error = %e, "failed to convert wallet pubkey for referral activation");
let _ = tx_status.send(TxStatusMsg::SetStatus {
title: s.tx_registration_failed.to_string(),
detail: format!("{}", e),
});
return;
}
};
match http
.invite()
.activate_referral(&authority, &referral_code)
.await
{
Ok(_) => {
let _ = tx_status.send(TxStatusMsg::SetStatus {
title: success_title,
detail: String::new(),
});
}
Err(e) => {
warn!(error = %e, code = %referral_code, "activate_referral failed");
let _ = tx_status.send(TxStatusMsg::SetStatus {
title: s.tx_registration_failed.to_string(),
detail: format!("{}", e),
});
}
}
});
}