use std::collections::HashMap;
use once_cell::sync::Lazy;
pub type FieldMapping = HashMap<&'static str, &'static str>;
pub type MethodFieldMappings = HashMap<&'static str, FieldMapping>;
pub static CEL_FIELD_MAPPINGS: Lazy<MethodFieldMappings> = Lazy::new(|| {
let mut mappings = HashMap::new();
mappings.insert(
"subscribe_wallet_balance",
HashMap::from([
("walletAddress", "a"),
("tokenAddress", "ta"),
("tokenPriceInUsd", "tpiu"),
("balance", "b"),
("timestamp", "t"),
]),
);
mappings.insert(
"subscribe_token_candles",
HashMap::from([
("open", "o"),
("close", "c"),
("high", "h"),
("low", "l"),
("volume", "v"),
("resolution", "r"),
("time", "t"),
("number", "n"),
]),
);
mappings.insert(
"subscribe_token_stats",
HashMap::from([
("address", "a"),
("timestamp", "t"),
("buys1m", "b1m"),
("sells1m", "s1m"),
("buyers1m", "be1m"),
("sellers1m", "se1m"),
("buyVolumeInUsd1m", "bviu1m"),
("sellVolumeInUsd1m", "sviu1m"),
("price1m", "p1m"),
("openInUsd1m", "oiu1m"),
("closeInUsd1m", "ciu1m"),
("buys5m", "b5m"),
("sells5m", "s5m"),
("buyers5m", "be5m"),
("sellers5m", "se5m"),
("buyVolumeInUsd5m", "bviu5m"),
("sellVolumeInUsd5m", "sviu5m"),
("price5m", "p5m"),
("openInUsd5m", "oiu5m"),
("closeInUsd5m", "ciu5m"),
("buys15m", "b15m"),
("sells15m", "s15m"),
("buyers15m", "be15m"),
("sellers15m", "se15m"),
("buyVolumeInUsd15m", "bviu15m"),
("sellVolumeInUsd15m", "sviu15m"),
("price15m", "p15m"),
("openInUsd15m", "oiu15m"),
("closeInUsd15m", "ciu15m"),
("buys30m", "b30m"),
("sells30m", "s30m"),
("buyers30m", "be30m"),
("sellers30m", "se30m"),
("buyVolumeInUsd30m", "bviu30m"),
("sellVolumeInUsd30m", "sviu30m"),
("price30m", "p30m"),
("openInUsd30m", "oiu30m"),
("closeInUsd30m", "ciu30m"),
("buys1h", "b1h"),
("sells1h", "s1h"),
("buyers1h", "be1h"),
("sellers1h", "se1h"),
("buyVolumeInUsd1h", "bviu1h"),
("sellVolumeInUsd1h", "sviu1h"),
("price1h", "p1h"),
("openInUsd1h", "oiu1h"),
("closeInUsd1h", "ciu1h"),
("buys4h", "b4h"),
("sells4h", "s4h"),
("buyers4h", "be4h"),
("sellers4h", "se4h"),
("buyVolumeInUsd4h", "bviu4h"),
("sellVolumeInUsd4h", "sviu4h"),
("price4h", "p4h"),
("openInUsd4h", "oiu4h"),
("closeInUsd4h", "ciu4h"),
("buys24h", "b24h"),
("sells24h", "s24h"),
("buyers24h", "be24h"),
("sellers24h", "se24h"),
("buyVolumeInUsd24h", "bviu24h"),
("sellVolumeInUsd24h", "sviu24h"),
("price24h", "p24h"),
("price", "p"),
("openInUsd24h", "oiu24h"),
("closeInUsd24h", "ciu24h"),
]),
);
mappings.insert(
"subscribe_token_holders",
HashMap::from([
("tokenAddress", "a"),
("holders", "h"),
("top100Amount", "t100a"),
("top10Amount", "t10a"),
("top100Holders", "t100h"),
("top10Holders", "t10h"),
("top100Ratio", "t100r"),
("top10Ratio", "t10r"),
("timestamp", "ts"),
]),
);
mappings.insert(
"subscribe_new_token",
HashMap::from([
("tokenAddress", "a"),
("name", "n"),
("symbol", "s"),
("decimals", "dec"),
("imageUrl", "iu"),
("description", "de"),
("createdAtMs", "cts"),
("coingeckoCoinId", "cgi"),
("socialMedia.twitter", "sm.tw"),
("socialMedia.telegram", "sm.tg"),
("socialMedia.website", "sm.w"),
("socialMedia.tiktok", "sm.tt"),
("socialMedia.discord", "sm.dc"),
("socialMedia.facebook", "sm.fb"),
("socialMedia.github", "sm.gh"),
("socialMedia.instagram", "sm.ig"),
("socialMedia.linkedin", "sm.li"),
("socialMedia.medium", "sm.md"),
("socialMedia.reddit", "sm.rd"),
("socialMedia.youtube", "sm.yt"),
("socialMedia.bitbucket", "sm.bb"),
("launchFrom.programAddress", "lf.pa"),
("launchFrom.protocolFamily", "lf.pf"),
("launchFrom.protocolName", "lf.pn"),
("migratedTo.programAddress", "mt.pa"),
("migratedTo.protocolFamily", "mt.pf"),
("migratedTo.protocolName", "mt.pn"),
]),
);
mappings.insert(
"subscribe_token_supply",
HashMap::from([("tokenAddress", "a"), ("supply", "s"), ("timestamp", "ts")]),
);
mappings.insert(
"subscribe_dex_pool_balance",
HashMap::from([
("poolAddress", "a"),
("tokenAAddress", "taa"),
("tokenALiquidityInUsd", "taliu"),
("tokenBAddress", "tba"),
("tokenBLiquidityInUsd", "tbliu"),
]),
);
mappings.insert(
"subscribe_token_liquidity",
HashMap::from([
("tokenAddress", "a"),
("metricType", "t"),
("value", "v"),
("timestamp", "ts"),
]),
);
mappings.insert(
"subscribe_new_tokens_metadata",
HashMap::from([
("tokenAddress", "a"),
("name", "n"),
("decimals", "dec"),
("symbol", "s"),
("imageUrl", "iu"),
("description", "de"),
("createdAtMs", "cts"),
("coingeckoCoinId", "cgi"),
("socialMedia.twitter", "sm.tw"),
("socialMedia.telegram", "sm.tg"),
("socialMedia.website", "sm.w"),
("socialMedia.tiktok", "sm.tt"),
("socialMedia.discord", "sm.dc"),
("socialMedia.facebook", "sm.fb"),
("socialMedia.github", "sm.gh"),
("socialMedia.instagram", "sm.ig"),
("socialMedia.linkedin", "sm.li"),
("socialMedia.medium", "sm.md"),
("socialMedia.reddit", "sm.rd"),
("socialMedia.youtube", "sm.yt"),
("socialMedia.bitbucket", "sm.bb"),
("launchFrom.programAddress", "lf.pa"),
("launchFrom.protocolFamily", "lf.pf"),
("launchFrom.protocolName", "lf.pn"),
("migratedTo.programAddress", "mt.pa"),
("migratedTo.protocolFamily", "mt.pf"),
("migratedTo.protocolName", "mt.pn"),
]),
);
mappings.insert(
"subscribe_new_tokens",
HashMap::from([
("tokenAddress", "a"),
("name", "n"),
("decimals", "dec"),
("symbol", "s"),
("imageUrl", "iu"),
("description", "de"),
("createdAtMs", "cts"),
("coingeckoCoinId", "cgi"),
("socialMedia.twitter", "sm.tw"),
("socialMedia.telegram", "sm.tg"),
("socialMedia.website", "sm.w"),
("socialMedia.tiktok", "sm.tt"),
("socialMedia.discord", "sm.dc"),
("socialMedia.facebook", "sm.fb"),
("socialMedia.github", "sm.gh"),
("socialMedia.instagram", "sm.ig"),
("socialMedia.linkedin", "sm.li"),
("socialMedia.medium", "sm.md"),
("socialMedia.reddit", "sm.rd"),
("socialMedia.youtube", "sm.yt"),
("socialMedia.bitbucket", "sm.bb"),
("launchFrom.programAddress", "lf.pa"),
("launchFrom.protocolFamily", "lf.pf"),
("launchFrom.protocolName", "lf.pn"),
("migratedTo.programAddress", "mt.pa"),
("migratedTo.protocolFamily", "mt.pf"),
("migratedTo.protocolName", "mt.pn"),
]),
);
mappings.insert(
"subscribe_token_trades",
HashMap::from([
("tokenAddress", "a"),
("timestamp", "t"),
("kind", "k"),
("buyAmount", "ba"),
("buyAmountInUsd", "baiu"),
("buyTokenAddress", "btma"),
("buyTokenName", "btn"),
("buyTokenSymbol", "bts"),
("buyWalletAddress", "bwa"),
("sellAmount", "sa"),
("sellAmountInUsd", "saiu"),
("sellTokenAddress", "stma"),
("sellTokenName", "stn"),
("sellTokenSymbol", "sts"),
("sellWalletAddress", "swa"),
("txHash", "h"),
]),
);
mappings.insert(
"subscribe_wallet_pnl",
HashMap::from([
("walletAddress", "a"),
("tokenAddress", "ta"),
("tokenPriceInUsd", "tpiu"),
("timestamp", "t"),
("opentime", "ot"),
("lasttime", "lt"),
("closetime", "ct"),
("buyAmount", "ba"),
("buyAmountInUsd", "baiu"),
("buyCount", "bs"),
("buyCount30d", "bs30d"),
("buyCount7d", "bs7d"),
("sellAmount", "sa"),
("sellAmountInUsd", "saiu"),
("sellCount", "ss"),
("sellCount30d", "ss30d"),
("sellCount7d", "ss7d"),
("heldDurationTimestamp", "hdts"),
("averageBuyPriceInUsd", "abpiu"),
("averageSellPriceInUsd", "aspiu"),
("unrealizedProfitInUsd", "upiu"),
("unrealizedProfitRatio", "upr"),
("realizedProfitInUsd", "rpiu"),
("realizedProfitRatio", "rpr"),
("totalRealizedProfitInUsd", "trpiu"),
("totalRealizedProfitRatio", "trr"),
]),
);
mappings.insert(
"subscribe_wallet_trade",
HashMap::from([
("tokenAddress", "a"),
("timestamp", "t"),
("kind", "k"),
("buyAmount", "ba"),
("buyAmountInUsd", "baiu"),
("buyTokenAddress", "btma"),
("buyTokenName", "btn"),
("buyTokenSymbol", "bts"),
("buyWalletAddress", "bwa"),
("sellAmount", "sa"),
("sellAmountInUsd", "saiu"),
("sellTokenAddress", "stma"),
("sellTokenName", "stn"),
("sellTokenSymbol", "sts"),
("sellWalletAddress", "swa"),
("txHash", "h"),
]),
);
mappings.insert(
"subscribe_token_max_liquidity",
HashMap::from([
("tokenAddress", "a"),
("poolAddress", "p"),
("liquidityInUsd", "liu"),
("liquidityInNative", "lin"),
("timestamp", "ts"),
]),
);
mappings.insert(
"subscribe_token_total_liquidity",
HashMap::from([
("tokenAddress", "a"),
("liquidityInUsd", "liu"),
("liquidityInNative", "lin"),
("poolCount", "pc"),
("timestamp", "ts"),
]),
);
mappings
});
pub fn get_field_mappings(method_name: &str) -> Option<&FieldMapping> {
CEL_FIELD_MAPPINGS.get(method_name)
}
pub fn replace_filter_fields(filter: &str, method_name: &str) -> String {
if filter.is_empty() {
return filter.to_string();
}
let field_mappings = match get_field_mappings(method_name) {
Some(m) => m,
None => return filter.to_string(),
};
let mut result = filter.to_string();
let mut entries: Vec<_> = field_mappings.iter().collect();
entries.sort_by(|a, b| b.0.len().cmp(&a.0.len()));
for (long_field, short_field) in entries {
let pattern1 = format!(r"\bmeta\.{}\b", regex::escape(long_field));
if let Ok(re) = regex::Regex::new(&pattern1) {
result = re
.replace_all(&result, format!("meta.{}", short_field))
.to_string();
}
let pattern2 = format!(r"\b{}\b", regex::escape(long_field));
if let Ok(re) = regex::Regex::new(&pattern2) {
result = re
.replace_all(&result, format!("meta.{}", short_field))
.to_string();
}
}
result
}
pub fn get_available_fields(method_name: &str) -> Vec<&'static str> {
match get_field_mappings(method_name) {
Some(mappings) => mappings.keys().copied().collect(),
None => Vec::new(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_field_mappings() {
let mappings = get_field_mappings("subscribe_token_candles");
assert!(mappings.is_some());
let mappings = mappings.unwrap();
assert_eq!(mappings.get("open"), Some(&"o"));
assert_eq!(mappings.get("close"), Some(&"c"));
}
#[test]
fn test_replace_filter_fields() {
let filter = "open > 100 && close < 200";
let result = replace_filter_fields(filter, "subscribe_token_candles");
assert!(result.contains("meta.o"));
assert!(result.contains("meta.c"));
}
#[test]
fn test_get_available_fields() {
let fields = get_available_fields("subscribe_token_candles");
assert!(fields.contains(&"open"));
assert!(fields.contains(&"close"));
assert!(fields.contains(&"high"));
assert!(fields.contains(&"low"));
}
}