0.5.3
This commit is contained in:
@@ -8,7 +8,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobot"
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
/// Early heuristic signal derived from classified activity.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum KhbbHeuristicSignal {
|
||||
/// Potential token account creation or initialization activity.
|
||||
/// Potential token account creation or update activity.
|
||||
PotentialTokenAccountActivity(KhbbPotentialTokenAccountActivitySignal),
|
||||
/// Potential mint-related activity.
|
||||
PotentialMintActivity(KhbbPotentialMintActivitySignal),
|
||||
/// Potential initial transaction activity around a token account.
|
||||
/// Potential associated token account activity.
|
||||
PotentialAssociatedTokenAccountActivity(KhbbPotentialAssociatedTokenAccountActivitySignal),
|
||||
/// Potential early transaction activity around a token flow.
|
||||
PotentialInitialTokenActivity(KhbbPotentialInitialTokenActivitySignal),
|
||||
/// Potential token bootstrap activity inferred from known logs/programs.
|
||||
PotentialTokenBootstrapActivity(KhbbPotentialTokenBootstrapActivitySignal),
|
||||
}
|
||||
|
||||
/// Heuristic signal indicating potential token account activity.
|
||||
@@ -37,6 +41,19 @@ pub struct KhbbPotentialMintActivitySignal {
|
||||
pub token_program_family: std::string::String,
|
||||
}
|
||||
|
||||
/// Heuristic signal indicating potential associated token account activity.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct KhbbPotentialAssociatedTokenAccountActivitySignal {
|
||||
/// Account pubkey involved in the signal.
|
||||
pub pubkey: std::string::String,
|
||||
/// Context slot.
|
||||
pub context_slot: u64,
|
||||
/// Subscription identifier.
|
||||
pub subscription_id: u64,
|
||||
/// Token program family.
|
||||
pub token_program_family: std::string::String,
|
||||
}
|
||||
|
||||
/// Heuristic signal indicating a possibly relevant early transaction activity.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct KhbbPotentialInitialTokenActivitySignal {
|
||||
@@ -52,68 +69,70 @@ pub struct KhbbPotentialInitialTokenActivitySignal {
|
||||
pub programs: std::vec::Vec<crate::KhbbKnownProgram>,
|
||||
}
|
||||
|
||||
/// Heuristic signal indicating a likely token bootstrap-related flow.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct KhbbPotentialTokenBootstrapActivitySignal {
|
||||
/// Transaction signature.
|
||||
pub signature: std::string::String,
|
||||
/// Context slot.
|
||||
pub context_slot: u64,
|
||||
/// Whether the transaction errored.
|
||||
pub has_error: bool,
|
||||
/// Whether a token program was seen.
|
||||
pub saw_token_program: bool,
|
||||
/// Whether an associated token program was seen.
|
||||
pub saw_associated_token_program: bool,
|
||||
/// Whether the system program was seen.
|
||||
pub saw_system_program: bool,
|
||||
/// Whether the compute budget program was seen.
|
||||
pub saw_compute_budget_program: bool,
|
||||
}
|
||||
|
||||
/// Derives early heuristic signals from classified domain events.
|
||||
pub(crate) fn derive_heuristic_signals(
|
||||
event: &crate::KhbbClassifiedDomainEvent,
|
||||
) -> core::result::Result<std::vec::Vec<KhbbHeuristicSignal>, crate::KhbbError> {
|
||||
match event {
|
||||
crate::KhbbClassifiedDomainEvent::SplTokenProgramActivity(activity) => {
|
||||
let mut signals = std::vec::Vec::<KhbbHeuristicSignal>::new();
|
||||
signals.push(KhbbHeuristicSignal::PotentialTokenAccountActivity(
|
||||
KhbbPotentialTokenAccountActivitySignal {
|
||||
pubkey: activity.pubkey.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
subscription_id: activity.subscription_id,
|
||||
token_program_family: std::string::String::from("spl-token"),
|
||||
derive_token_program_activity_signals(
|
||||
activity.subscription_id,
|
||||
&activity.pubkey,
|
||||
activity.context_slot,
|
||||
"spl-token",
|
||||
)
|
||||
},
|
||||
));
|
||||
if activity.pubkey != crate::ids::WSOL_MINT_ID.to_string() {
|
||||
signals.push(KhbbHeuristicSignal::PotentialMintActivity(
|
||||
KhbbPotentialMintActivitySignal {
|
||||
pubkey: activity.pubkey.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
token_program_family: std::string::String::from("spl-token"),
|
||||
},
|
||||
));
|
||||
}
|
||||
Ok(signals)
|
||||
}
|
||||
crate::KhbbClassifiedDomainEvent::SplToken2022ProgramActivity(activity) => {
|
||||
let mut signals = std::vec::Vec::<KhbbHeuristicSignal>::new();
|
||||
signals.push(KhbbHeuristicSignal::PotentialTokenAccountActivity(
|
||||
KhbbPotentialTokenAccountActivitySignal {
|
||||
pubkey: activity.pubkey.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
subscription_id: activity.subscription_id,
|
||||
token_program_family: std::string::String::from("spl-token-2022"),
|
||||
derive_token_program_activity_signals(
|
||||
activity.subscription_id,
|
||||
&activity.pubkey,
|
||||
activity.context_slot,
|
||||
"spl-token-2022",
|
||||
)
|
||||
},
|
||||
));
|
||||
signals.push(KhbbHeuristicSignal::PotentialMintActivity(
|
||||
KhbbPotentialMintActivitySignal {
|
||||
pubkey: activity.pubkey.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
token_program_family: std::string::String::from("spl-token-2022"),
|
||||
},
|
||||
));
|
||||
Ok(signals)
|
||||
}
|
||||
crate::KhbbClassifiedDomainEvent::KnownProgramLogActivity(activity) => {
|
||||
let mut contains_token_program = false;
|
||||
let mut signals = std::vec::Vec::<KhbbHeuristicSignal>::new();
|
||||
let mut saw_token_program = false;
|
||||
let mut saw_associated_token_program = false;
|
||||
let mut saw_system_program = false;
|
||||
let mut saw_compute_budget_program = false;
|
||||
for program in &activity.programs {
|
||||
match program {
|
||||
crate::KhbbKnownProgram::SplToken
|
||||
| crate::KhbbKnownProgram::SplToken2022
|
||||
| crate::KhbbKnownProgram::AssociatedTokenAccount => {
|
||||
contains_token_program = true;
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
crate::KhbbKnownProgram::SplToken | crate::KhbbKnownProgram::SplToken2022 => {
|
||||
saw_token_program = true;
|
||||
},
|
||||
crate::KhbbKnownProgram::AssociatedTokenAccount => {
|
||||
saw_associated_token_program = true;
|
||||
},
|
||||
crate::KhbbKnownProgram::System => {
|
||||
saw_system_program = true;
|
||||
},
|
||||
crate::KhbbKnownProgram::ComputeBudget => {
|
||||
saw_compute_budget_program = true;
|
||||
},
|
||||
}
|
||||
}
|
||||
if !contains_token_program {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
Ok(vec![KhbbHeuristicSignal::PotentialInitialTokenActivity(
|
||||
if saw_token_program || saw_associated_token_program {
|
||||
signals.push(KhbbHeuristicSignal::PotentialInitialTokenActivity(
|
||||
KhbbPotentialInitialTokenActivitySignal {
|
||||
signature: activity.signature.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
@@ -121,12 +140,68 @@ pub(crate) fn derive_heuristic_signals(
|
||||
log_count: activity.programs.len(),
|
||||
programs: activity.programs.clone(),
|
||||
},
|
||||
)])
|
||||
));
|
||||
}
|
||||
if saw_token_program && (saw_associated_token_program || saw_system_program) {
|
||||
signals.push(KhbbHeuristicSignal::PotentialTokenBootstrapActivity(
|
||||
KhbbPotentialTokenBootstrapActivitySignal {
|
||||
signature: activity.signature.clone(),
|
||||
context_slot: activity.context_slot,
|
||||
has_error: activity.has_error,
|
||||
saw_token_program,
|
||||
saw_associated_token_program,
|
||||
saw_system_program,
|
||||
saw_compute_budget_program,
|
||||
},
|
||||
));
|
||||
}
|
||||
Ok(signals)
|
||||
},
|
||||
crate::KhbbClassifiedDomainEvent::UnknownProgramLogActivity(_) => Ok(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_token_program_activity_signals(
|
||||
subscription_id: u64,
|
||||
pubkey: &str,
|
||||
context_slot: u64,
|
||||
token_program_family: &str,
|
||||
) -> core::result::Result<std::vec::Vec<KhbbHeuristicSignal>, crate::KhbbError> {
|
||||
let mut signals = std::vec::Vec::<KhbbHeuristicSignal>::new();
|
||||
signals.push(KhbbHeuristicSignal::PotentialTokenAccountActivity(
|
||||
KhbbPotentialTokenAccountActivitySignal {
|
||||
pubkey: std::string::String::from(pubkey),
|
||||
context_slot,
|
||||
subscription_id,
|
||||
token_program_family: std::string::String::from(token_program_family),
|
||||
},
|
||||
));
|
||||
let wsol_text = crate::ids::WSOL_MINT_ID.to_string();
|
||||
if pubkey != wsol_text {
|
||||
signals.push(KhbbHeuristicSignal::PotentialMintActivity(KhbbPotentialMintActivitySignal {
|
||||
pubkey: std::string::String::from(pubkey),
|
||||
context_slot,
|
||||
token_program_family: std::string::String::from(token_program_family),
|
||||
}));
|
||||
}
|
||||
if looks_like_associated_token_account(pubkey) {
|
||||
signals.push(KhbbHeuristicSignal::PotentialAssociatedTokenAccountActivity(
|
||||
KhbbPotentialAssociatedTokenAccountActivitySignal {
|
||||
pubkey: std::string::String::from(pubkey),
|
||||
context_slot,
|
||||
subscription_id,
|
||||
token_program_family: std::string::String::from(token_program_family),
|
||||
},
|
||||
));
|
||||
}
|
||||
Ok(signals)
|
||||
}
|
||||
|
||||
fn looks_like_associated_token_account(pubkey: &str) -> bool {
|
||||
let length = pubkey.len();
|
||||
length >= 32 && length <= 44
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
@@ -141,11 +216,11 @@ mod tests {
|
||||
let result = super::derive_heuristic_signals(&event);
|
||||
assert!(result.is_ok());
|
||||
let signals = result.expect("derive spl-token signals");
|
||||
assert_eq!(signals.len(), 2);
|
||||
assert!(signals.len() >= 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_heuristics_from_known_program_logs_returns_signal_when_token_program_seen() {
|
||||
fn derive_heuristics_from_known_program_logs_returns_signals_when_token_program_seen() {
|
||||
let event = crate::KhbbClassifiedDomainEvent::KnownProgramLogActivity(
|
||||
crate::KhbbKnownProgramLogActivityEvent {
|
||||
signature: std::string::String::from("sig-1"),
|
||||
@@ -163,11 +238,31 @@ mod tests {
|
||||
assert_eq!(signals.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_heuristics_from_known_program_logs_returns_bootstrap_signal_when_system_seen() {
|
||||
let event = crate::KhbbClassifiedDomainEvent::KnownProgramLogActivity(
|
||||
crate::KhbbKnownProgramLogActivityEvent {
|
||||
signature: std::string::String::from("sig-2"),
|
||||
context_slot: 201,
|
||||
has_error: false,
|
||||
programs: vec![
|
||||
crate::KhbbKnownProgram::ComputeBudget,
|
||||
crate::KhbbKnownProgram::System,
|
||||
crate::KhbbKnownProgram::SplToken,
|
||||
],
|
||||
},
|
||||
);
|
||||
let result = super::derive_heuristic_signals(&event);
|
||||
assert!(result.is_ok());
|
||||
let signals = result.expect("derive bootstrap signals");
|
||||
assert_eq!(signals.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_heuristics_from_unknown_program_logs_returns_no_signal() {
|
||||
let event = crate::KhbbClassifiedDomainEvent::UnknownProgramLogActivity(
|
||||
crate::KhbbUnknownProgramLogActivityEvent {
|
||||
signature: std::string::String::from("sig-2"),
|
||||
signature: std::string::String::from("sig-3"),
|
||||
context_slot: 300,
|
||||
has_error: false,
|
||||
log_count: 2,
|
||||
@@ -178,4 +273,11 @@ mod tests {
|
||||
let signals = result.expect("derive unknown log signals");
|
||||
assert!(signals.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn looks_like_associated_token_account_accepts_base58_like_length() {
|
||||
assert!(super::looks_like_associated_token_account(
|
||||
"24Ux1iXBGBgx83SNX9SZkSkwxDLsK1HjXhcuMMsNduVn"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,3 +109,7 @@ pub use crate::heuristics::KhbbPotentialTokenAccountActivitySignal;
|
||||
pub use crate::heuristics::KhbbPotentialMintActivitySignal;
|
||||
/// Heuristic signal indicating a possibly relevant early transaction activity.
|
||||
pub use crate::heuristics::KhbbPotentialInitialTokenActivitySignal;
|
||||
/// Heuristic signal indicating potential associated token account activity.
|
||||
pub use crate::heuristics::KhbbPotentialAssociatedTokenAccountActivitySignal;
|
||||
/// Heuristic signal indicating a likely token bootstrap-related flow.
|
||||
pub use crate::heuristics::KhbbPotentialTokenBootstrapActivitySignal;
|
||||
|
||||
@@ -479,8 +479,22 @@ pub async fn run_listener_runtime(
|
||||
"heuristic potential initial token activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialTokenBootstrapActivity(inner) => {
|
||||
tracing::trace!(
|
||||
listener_session_id = session.id,
|
||||
signature = %inner.signature,
|
||||
context_slot = inner.context_slot,
|
||||
has_error = inner.has_error,
|
||||
saw_token_program = inner.saw_token_program,
|
||||
saw_associated_token_program = inner.saw_associated_token_program,
|
||||
saw_system_program = inner.saw_system_program,
|
||||
saw_compute_budget_program = inner.saw_compute_budget_program,
|
||||
"heuristic potential token bootstrap activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialTokenAccountActivity(_) => {}
|
||||
crate::KhbbHeuristicSignal::PotentialMintActivity(_) => {}
|
||||
crate::KhbbHeuristicSignal::PotentialAssociatedTokenAccountActivity(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,7 +583,18 @@ pub async fn run_listener_runtime(
|
||||
"heuristic potential mint activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialAssociatedTokenAccountActivity(inner) => {
|
||||
tracing::trace!(
|
||||
listener_session_id = session.id,
|
||||
pubkey = %inner.pubkey,
|
||||
context_slot = inner.context_slot,
|
||||
subscription_id = inner.subscription_id,
|
||||
token_program_family = %inner.token_program_family,
|
||||
"heuristic potential associated token account activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialInitialTokenActivity(_) => {}
|
||||
crate::KhbbHeuristicSignal::PotentialTokenBootstrapActivity(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -619,7 +644,18 @@ pub async fn run_listener_runtime(
|
||||
"heuristic potential mint activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialAssociatedTokenAccountActivity(inner) => {
|
||||
tracing::trace!(
|
||||
listener_session_id = session.id,
|
||||
pubkey = %inner.pubkey,
|
||||
context_slot = inner.context_slot,
|
||||
subscription_id = inner.subscription_id,
|
||||
token_program_family = %inner.token_program_family,
|
||||
"heuristic potential associated token account activity signal"
|
||||
);
|
||||
}
|
||||
crate::KhbbHeuristicSignal::PotentialInitialTokenActivity(_) => {}
|
||||
crate::KhbbHeuristicSignal::PotentialTokenBootstrapActivity(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user