This commit is contained in:
2026-05-05 05:03:11 +02:00
parent 3e994995d7
commit f2c227e08f
132 changed files with 5767 additions and 4461 deletions

View File

@@ -76,7 +76,7 @@ enum KbDexlabInstructionKind {
impl KbDexlabDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more DexLab events.
@@ -93,7 +93,7 @@ impl KbDexlabDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -104,7 +104,7 @@ impl KbDexlabDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -140,45 +140,24 @@ impl KbDexlabDecoder {
kb_classify_instruction_kind(parsed_json.as_ref(), &log_messages);
let pool_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"pool",
"poolAddress",
"poolAccount",
"amm",
"ammPool",
"poolState",
],
&["pool", "poolAddress", "poolAccount", "amm", "ammPool", "poolState"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenA",
"tokenAMint",
"mintA",
"baseMint",
"token0Mint",
"mint0",
],
&["tokenA", "tokenAMint", "mintA", "baseMint", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenB",
"tokenBMint",
"mintB",
"quoteMint",
"token1Mint",
"mint1",
],
&["tokenB", "tokenBMint", "mintB", "quoteMint", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["payer", "creator", "user", "owner"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let fee_tier = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["feeTier", "fee_tier", "tradeFeeTier", "feeRate"],
@@ -246,7 +225,7 @@ impl KbDexlabDecoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -278,7 +257,7 @@ fn kb_classify_instruction_kind(
if kb_log_messages_contain_keyword(log_messages, "swap") {
return KbDexlabInstructionKind::Swap;
}
KbDexlabInstructionKind::Unknown
return KbDexlabInstructionKind::Unknown;
}
fn kb_extract_log_messages(
@@ -305,7 +284,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -316,7 +295,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_normalize_text(value: &str) -> std::string::String {
@@ -326,7 +305,7 @@ fn kb_normalize_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -340,7 +319,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -349,7 +328,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -361,11 +340,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -377,7 +358,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -412,7 +393,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_extract_account(
@@ -422,7 +403,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
@@ -432,7 +413,7 @@ fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTra
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
#[cfg(test)]
@@ -462,7 +443,7 @@ mod tests {
.to_string(),
);
dto.id = Some(801);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -498,7 +479,7 @@ mod tests {
),
);
dto.id = Some(802);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -526,7 +507,7 @@ mod tests {
.to_string(),
);
dto.id = Some(803);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -559,7 +540,7 @@ mod tests {
),
);
dto.id = Some(804);
dto
return dto;
}
#[test]
@@ -584,10 +565,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert_eq!(event.fee_tier, Some("0.3%".to_string()));
}
},
crate::KbDexlabDecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -612,10 +593,10 @@ mod tests {
event.token_b_mint,
Some("So11111111111111111111111111111111111111112".to_string())
);
}
},
crate::KbDexlabDecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
}

View File

@@ -76,7 +76,7 @@ enum KbFluxbeamInstructionKind {
impl KbFluxbeamDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more FluxBeam events.
@@ -93,7 +93,7 @@ impl KbFluxbeamDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -104,7 +104,7 @@ impl KbFluxbeamDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -140,50 +140,29 @@ impl KbFluxbeamDecoder {
kb_classify_instruction_kind(parsed_json.as_ref(), &log_messages);
let pool_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"pool",
"poolAddress",
"poolAccount",
"amm",
"ammPool",
"poolState",
],
&["pool", "poolAddress", "poolAccount", "amm", "ammPool", "poolState"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let lp_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["lpMint", "lp_mint", "lpTokenMint"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenA",
"tokenAMint",
"mintA",
"baseMint",
"token0Mint",
"mint0",
],
&["tokenA", "tokenAMint", "mintA", "baseMint", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenB",
"tokenBMint",
"mintB",
"quoteMint",
"token1Mint",
"mint1",
],
&["tokenB", "tokenBMint", "mintB", "quoteMint", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["payer", "creator", "user", "owner"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
if instruction_kind == KbFluxbeamInstructionKind::CreatePool {
let payload_json = serde_json::json!({
"decoder": "fluxbeam",
@@ -247,7 +226,7 @@ impl KbFluxbeamDecoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -278,7 +257,7 @@ fn kb_classify_instruction_kind(
if kb_log_messages_contain_keyword(log_messages, "swap") {
return KbFluxbeamInstructionKind::Swap;
}
KbFluxbeamInstructionKind::Unknown
return KbFluxbeamInstructionKind::Unknown;
}
fn kb_extract_log_messages(
@@ -305,7 +284,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -316,7 +295,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_normalize_text(value: &str) -> std::string::String {
@@ -326,7 +305,7 @@ fn kb_normalize_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -340,7 +319,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -349,7 +328,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -361,11 +340,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -377,7 +358,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -412,7 +393,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_extract_account(
@@ -422,7 +403,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
@@ -432,7 +413,7 @@ fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTra
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
#[cfg(test)]
@@ -462,7 +443,7 @@ mod tests {
.to_string(),
);
dto.id = Some(701);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -499,7 +480,7 @@ mod tests {
),
);
dto.id = Some(702);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -527,7 +508,7 @@ mod tests {
.to_string(),
);
dto.id = Some(703);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -561,7 +542,7 @@ mod tests {
),
);
dto.id = Some(704);
dto
return dto;
}
#[test]
@@ -586,10 +567,10 @@ mod tests {
event.token_b_mint,
Some("So11111111111111111111111111111111111111112".to_string())
);
}
},
crate::KbFluxbeamDecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -614,10 +595,10 @@ mod tests {
event.token_b_mint,
Some("So11111111111111111111111111111111111111112".to_string())
);
}
},
crate::KbFluxbeamDecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
}

View File

@@ -79,7 +79,7 @@ enum KbMeteoraDammV1InstructionKind {
impl KbMeteoraDammV1Decoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Meteora DAMM v1 events.
@@ -96,7 +96,7 @@ impl KbMeteoraDammV1Decoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -107,7 +107,7 @@ impl KbMeteoraDammV1Decoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -143,50 +143,29 @@ impl KbMeteoraDammV1Decoder {
kb_classify_instruction_kind(parsed_json.as_ref(), &log_messages);
let pool_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"pool",
"poolAddress",
"poolAccount",
"amm",
"ammPool",
"poolState",
],
&["pool", "poolAddress", "poolAccount", "amm", "ammPool", "poolState"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenAMint",
"mintA",
"baseMint",
"token0Mint",
"mint0",
"coinMint",
],
&["tokenAMint", "mintA", "baseMint", "token0Mint", "mint0", "coinMint"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenBMint",
"mintB",
"quoteMint",
"token1Mint",
"mint1",
"pcMint",
],
&["tokenBMint", "mintB", "quoteMint", "token1Mint", "mint1", "pcMint"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let config_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["config", "poolConfig", "ammConfig", "tradeFeeConfig"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["creator", "payer", "user", "owner"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
if instruction_kind == KbMeteoraDammV1InstructionKind::CreatePool
|| instruction_kind == KbMeteoraDammV1InstructionKind::CreatePoolWithConfig
{
@@ -257,7 +236,7 @@ impl KbMeteoraDammV1Decoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -297,7 +276,7 @@ fn kb_classify_instruction_kind(
if kb_log_messages_contain_keyword(log_messages, "swap") {
return KbMeteoraDammV1InstructionKind::Swap;
}
KbMeteoraDammV1InstructionKind::Unknown
return KbMeteoraDammV1InstructionKind::Unknown;
}
fn kb_extract_log_messages(
@@ -325,7 +304,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -336,7 +315,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_normalize_text(value: &str) -> std::string::String {
@@ -346,7 +325,7 @@ fn kb_normalize_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -360,7 +339,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -369,7 +348,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -381,11 +360,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -397,7 +378,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -432,7 +413,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_value_contains_any_key(
@@ -443,7 +424,7 @@ fn kb_value_contains_any_key(
Some(value) => value,
None => return false,
};
kb_value_contains_any_key_inner(value, candidate_keys)
return kb_value_contains_any_key_inner(value, candidate_keys);
}
fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[&str]) -> bool {
@@ -467,7 +448,7 @@ fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[
}
}
}
false
return false;
}
fn kb_extract_account(
@@ -477,7 +458,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
@@ -487,7 +468,7 @@ fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTra
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
#[cfg(test)]
@@ -517,7 +498,7 @@ mod tests {
.to_string(),
);
dto.id = Some(501);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -554,7 +535,7 @@ mod tests {
),
);
dto.id = Some(502);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -582,7 +563,7 @@ mod tests {
.to_string(),
);
dto.id = Some(503);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -615,7 +596,7 @@ mod tests {
),
);
dto.id = Some(504);
dto
return dto;
}
#[test]
@@ -640,10 +621,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert!(event.used_config);
}
},
crate::KbMeteoraDammV1DecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -668,10 +649,10 @@ mod tests {
event.token_b_mint,
Some("So11111111111111111111111111111111111111112".to_string())
);
}
},
crate::KbMeteoraDammV1DecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
}

View File

@@ -82,7 +82,7 @@ enum KbMeteoraDammV2InstructionKind {
impl KbMeteoraDammV2Decoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Meteora DAMM v2 events.
@@ -99,7 +99,7 @@ impl KbMeteoraDammV2Decoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -110,7 +110,7 @@ impl KbMeteoraDammV2Decoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -148,27 +148,27 @@ impl KbMeteoraDammV2Decoder {
parsed_json.as_ref(),
&["pool", "poolAddress", "poolAccount", "poolState", "cpAmm"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["tokenAMint", "mintA", "baseMint", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["tokenBMint", "mintB", "quoteMint", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let config_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["staticConfig", "dynamicConfig", "config", "poolConfig"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["creator", "payer", "user", "owner"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
if instruction_kind == KbMeteoraDammV2InstructionKind::CreatePoolStatic
|| instruction_kind == KbMeteoraDammV2InstructionKind::CreatePoolDynamic
|| instruction_kind == KbMeteoraDammV2InstructionKind::CreatePoolCustomizable
@@ -178,7 +178,7 @@ impl KbMeteoraDammV2Decoder {
KbMeteoraDammV2InstructionKind::CreatePoolDynamic => "dynamic".to_string(),
KbMeteoraDammV2InstructionKind::CreatePoolCustomizable => {
"customizable".to_string()
}
},
_ => "unknown".to_string(),
};
let payload_json = serde_json::json!({
@@ -249,7 +249,7 @@ impl KbMeteoraDammV2Decoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -278,7 +278,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_classify_instruction_kind(
@@ -333,7 +333,7 @@ fn kb_classify_instruction_kind(
{
return KbMeteoraDammV2InstructionKind::Swap;
}
KbMeteoraDammV2InstructionKind::Unknown
return KbMeteoraDammV2InstructionKind::Unknown;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -344,7 +344,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_normalize_text(value: &str) -> std::string::String {
@@ -354,7 +354,7 @@ fn kb_normalize_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -368,7 +368,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -377,7 +377,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -389,11 +389,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -405,7 +407,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -440,7 +442,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_value_contains_any_key(
@@ -451,7 +453,7 @@ fn kb_value_contains_any_key(
Some(value) => value,
None => return false,
};
kb_value_contains_any_key_inner(value, candidate_keys)
return kb_value_contains_any_key_inner(value, candidate_keys);
}
fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[&str]) -> bool {
@@ -475,7 +477,7 @@ fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[
}
}
}
false
return false;
}
fn kb_extract_account(
@@ -485,7 +487,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
@@ -495,7 +497,7 @@ fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTra
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
#[cfg(test)]
@@ -525,7 +527,7 @@ mod tests {
.to_string(),
);
dto.id = Some(401);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -562,7 +564,7 @@ mod tests {
),
);
dto.id = Some(402);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -590,7 +592,7 @@ mod tests {
.to_string(),
);
dto.id = Some(403);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -623,7 +625,7 @@ mod tests {
),
);
dto.id = Some(404);
dto
return dto;
}
#[test]
@@ -648,10 +650,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert_eq!(event.create_kind, "customizable".to_string());
}
},
crate::KbMeteoraDammV2DecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -677,10 +679,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert!(event.used_swap2);
}
},
crate::KbMeteoraDammV2DecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
}

View File

@@ -76,7 +76,7 @@ pub struct KbMeteoraDbcDecoder;
impl KbMeteoraDbcDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Meteora DBC events.
@@ -93,7 +93,7 @@ impl KbMeteoraDbcDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -104,7 +104,7 @@ impl KbMeteoraDbcDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -142,27 +142,27 @@ impl KbMeteoraDbcDecoder {
parsed_json.as_ref(),
&["pool", "poolAccount", "poolState", "virtualPool", "poolKey"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["baseMint", "tokenAMint", "mintA", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["quoteMint", "tokenBMint", "mintB", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let config_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["poolConfig", "config", "dbcConfig", "curveConfig"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["creator", "poolCreator", "owner", "user"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
if instruction_kind == KbMeteoraDbcInstructionKind::CreatePool {
let payload_json = serde_json::json!({
"decoder": "meteora_dbc",
@@ -228,7 +228,7 @@ impl KbMeteoraDbcDecoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -257,7 +257,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_any_keyword(
@@ -269,7 +269,7 @@ fn kb_log_messages_contain_any_keyword(
return true;
}
}
false
return false;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -280,7 +280,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_normalize_log_text(value: &str) -> std::string::String {
@@ -290,7 +290,7 @@ fn kb_normalize_log_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -304,7 +304,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -313,7 +313,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -325,11 +325,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -341,7 +343,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -376,7 +378,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_value_contains_any_key(
@@ -387,7 +389,7 @@ fn kb_value_contains_any_key(
Some(value) => value,
None => return false,
};
kb_value_contains_any_key_inner(value, candidate_keys)
return kb_value_contains_any_key_inner(value, candidate_keys);
}
fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[&str]) -> bool {
@@ -411,7 +413,7 @@ fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[
}
}
}
false
return false;
}
fn kb_extract_account(
@@ -421,7 +423,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
@@ -431,7 +433,7 @@ fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTra
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
fn kb_classify_instruction_kind(
@@ -456,32 +458,21 @@ fn kb_classify_instruction_kind(
}
let has_create_config = kb_value_contains_any_key(
parsed_json,
&[
"poolConfig",
"migrationQuoteThreshold",
"curveConfig",
"dbcConfig",
],
&["poolConfig", "migrationQuoteThreshold", "curveConfig", "dbcConfig"],
);
if has_create_config {
return KbMeteoraDbcInstructionKind::CreatePool;
}
if kb_log_messages_contain_any_keyword(
log_messages,
&[
"create_pool",
"createpool",
"initialize_pool",
"initializepool",
"launch_pool",
],
&["create_pool", "createpool", "initialize_pool", "initializepool", "launch_pool"],
) {
return KbMeteoraDbcInstructionKind::CreatePool;
}
if kb_log_messages_contain_any_keyword(log_messages, &["swap2", "swap"]) {
return KbMeteoraDbcInstructionKind::Swap;
}
KbMeteoraDbcInstructionKind::Unknown
return KbMeteoraDbcInstructionKind::Unknown;
}
#[cfg(test)]
@@ -511,7 +502,7 @@ mod tests {
.to_string(),
);
dto.id = Some(301);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -547,7 +538,7 @@ mod tests {
),
);
dto.id = Some(302);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -575,7 +566,7 @@ mod tests {
.to_string(),
);
dto.id = Some(303);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -607,7 +598,7 @@ mod tests {
),
);
dto.id = Some(304);
dto
return dto;
}
#[test]
@@ -632,10 +623,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert_eq!(event.config_account, Some("DbcConfig111".to_string()));
}
},
crate::KbMeteoraDbcDecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -660,10 +651,10 @@ mod tests {
event.token_b_mint,
Some("So11111111111111111111111111111111111111112".to_string())
);
}
},
crate::KbMeteoraDbcDecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
@@ -687,10 +678,10 @@ mod tests {
};
assert_eq!(decoded.len(), 1);
match &decoded[0] {
crate::KbMeteoraDbcDecodedEvent::Swap(_) => {}
crate::KbMeteoraDbcDecodedEvent::Swap(_) => {},
crate::KbMeteoraDbcDecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
@@ -706,10 +697,10 @@ mod tests {
};
assert_eq!(decoded.len(), 1);
match &decoded[0] {
crate::KbMeteoraDbcDecodedEvent::CreatePool(_) => {}
crate::KbMeteoraDbcDecodedEvent::CreatePool(_) => {},
crate::KbMeteoraDbcDecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
}

View File

@@ -3,8 +3,7 @@
//! Orca Whirlpools transaction decoder.
/// Orca Whirlpools program id.
pub const KB_ORCA_WHIRLPOOLS_PROGRAM_ID: &str =
"whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc";
pub const KB_ORCA_WHIRLPOOLS_PROGRAM_ID: &str = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc";
/// Decoded Orca Whirlpools create-pool event.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -83,7 +82,7 @@ enum KbOrcaWhirlpoolsInstructionKind {
impl KbOrcaWhirlpoolsDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Orca Whirlpools events.
@@ -100,7 +99,7 @@ impl KbOrcaWhirlpoolsDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -111,7 +110,7 @@ impl KbOrcaWhirlpoolsDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -137,7 +136,8 @@ impl KbOrcaWhirlpoolsDecoder {
Ok(accounts) => accounts,
Err(error) => return Err(error),
};
let parsed_json_result = kb_parse_optional_parsed_json(instruction.parsed_json.as_ref());
let parsed_json_result =
kb_parse_optional_parsed_json(instruction.parsed_json.as_ref());
let parsed_json = match parsed_json_result {
Ok(parsed_json) => parsed_json,
Err(error) => return Err(error),
@@ -146,59 +146,33 @@ impl KbOrcaWhirlpoolsDecoder {
kb_classify_instruction_kind(parsed_json.as_ref(), &log_messages);
let pool_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"whirlpool",
"pool",
"poolAddress",
"poolAccount",
"whirlpoolAddress",
],
&["whirlpool", "pool", "poolAddress", "poolAccount", "whirlpoolAddress"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenMintA",
"tokenAMint",
"mintA",
"baseMint",
"token0Mint",
"mint0",
],
&["tokenMintA", "tokenAMint", "mintA", "baseMint", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 1));
.or_else(|| return kb_extract_account(&accounts, 1));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenMintB",
"tokenBMint",
"mintB",
"quoteMint",
"token1Mint",
"mint1",
],
&["tokenMintB", "tokenBMint", "mintB", "quoteMint", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 2));
.or_else(|| return kb_extract_account(&accounts, 2));
let config_account = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"whirlpoolsConfig",
"config",
"configAccount",
"whirlpoolConfig",
],
&["whirlpoolsConfig", "config", "configAccount", "whirlpoolConfig"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let creator = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&["funder", "creator", "payer", "user", "owner"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
if instruction_kind == KbOrcaWhirlpoolsInstructionKind::InitializePool
|| instruction_kind == KbOrcaWhirlpoolsInstructionKind::InitializePoolV2
{
let used_v2 =
instruction_kind == KbOrcaWhirlpoolsInstructionKind::InitializePoolV2;
let used_v2 = instruction_kind == KbOrcaWhirlpoolsInstructionKind::InitializePoolV2;
let payload_json = serde_json::json!({
"decoder": "orca_whirlpools",
"eventKind": "create_pool",
@@ -268,7 +242,7 @@ impl KbOrcaWhirlpoolsDecoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -295,17 +269,13 @@ fn kb_classify_instruction_kind(
return KbOrcaWhirlpoolsInstructionKind::Swap;
}
}
if kb_value_contains_any_key(
parsed_json,
&["tokenProgramA", "tokenProgramB", "memoProgram"],
) && kb_log_messages_contain_keyword(log_messages, "initialize_pool")
if kb_value_contains_any_key(parsed_json, &["tokenProgramA", "tokenProgramB", "memoProgram"])
&& kb_log_messages_contain_keyword(log_messages, "initialize_pool")
{
return KbOrcaWhirlpoolsInstructionKind::InitializePoolV2;
}
if kb_value_contains_any_key(
parsed_json,
&["tokenProgramA", "tokenProgramB", "memoProgram"],
) && kb_log_messages_contain_keyword(log_messages, "swap")
if kb_value_contains_any_key(parsed_json, &["tokenProgramA", "tokenProgramB", "memoProgram"])
&& kb_log_messages_contain_keyword(log_messages, "swap")
{
return KbOrcaWhirlpoolsInstructionKind::SwapV2;
}
@@ -327,7 +297,7 @@ fn kb_classify_instruction_kind(
if kb_log_messages_contain_keyword(log_messages, "swap") {
return KbOrcaWhirlpoolsInstructionKind::Swap;
}
KbOrcaWhirlpoolsInstructionKind::Unknown
return KbOrcaWhirlpoolsInstructionKind::Unknown;
}
fn kb_extract_log_messages(
@@ -355,13 +325,10 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(
log_messages: &[std::string::String],
keyword: &str,
) -> bool {
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
let keyword_normalized = kb_normalize_text(keyword);
for log_message in log_messages {
let log_normalized = kb_normalize_text(log_message.as_str());
@@ -369,7 +336,7 @@ fn kb_log_messages_contain_keyword(
return true;
}
}
false
return false;
}
fn kb_normalize_text(value: &str) -> std::string::String {
@@ -379,7 +346,7 @@ fn kb_normalize_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
fn kb_parse_accounts_json(
@@ -393,7 +360,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -402,7 +369,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_parse_optional_parsed_json(
@@ -414,11 +381,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -430,7 +399,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -466,7 +435,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
fn kb_value_contains_any_key(
@@ -477,13 +446,10 @@ fn kb_value_contains_any_key(
Some(value) => value,
None => return false,
};
kb_value_contains_any_key_inner(value, candidate_keys)
return kb_value_contains_any_key_inner(value, candidate_keys);
}
fn kb_value_contains_any_key_inner(
value: &serde_json::Value,
candidate_keys: &[&str],
) -> bool {
fn kb_value_contains_any_key_inner(value: &serde_json::Value, candidate_keys: &[&str]) -> bool {
if let Some(object) = value.as_object() {
for candidate_key in candidate_keys {
if object.contains_key(*candidate_key) {
@@ -504,7 +470,7 @@ fn kb_value_contains_any_key_inner(
}
}
}
false
return false;
}
fn kb_extract_account(
@@ -514,19 +480,17 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_infer_trade_side(
log_messages: &[std::string::String],
) -> crate::KbSwapTradeSide {
fn kb_infer_trade_side(log_messages: &[std::string::String]) -> crate::KbSwapTradeSide {
if kb_log_messages_contain_keyword(log_messages, "buy") {
return crate::KbSwapTradeSide::BuyBase;
}
if kb_log_messages_contain_keyword(log_messages, "sell") {
return crate::KbSwapTradeSide::SellBase;
}
crate::KbSwapTradeSide::Unknown
return crate::KbSwapTradeSide::Unknown;
}
#[cfg(test)]
@@ -556,7 +520,7 @@ mod tests {
.to_string(),
);
dto.id = Some(601);
dto
return dto;
}
fn make_create_instruction() -> crate::KbChainInstructionDto {
@@ -595,7 +559,7 @@ mod tests {
),
);
dto.id = Some(602);
dto
return dto;
}
fn make_swap_transaction() -> crate::KbChainTransactionDto {
@@ -623,7 +587,7 @@ mod tests {
.to_string(),
);
dto.id = Some(603);
dto
return dto;
}
fn make_swap_instruction() -> crate::KbChainInstructionDto {
@@ -656,7 +620,7 @@ mod tests {
),
);
dto.id = Some(604);
dto
return dto;
}
#[test]
@@ -682,10 +646,10 @@ mod tests {
);
assert_eq!(event.config_account, Some("OrcaConfig111".to_string()));
assert!(event.used_v2);
}
},
crate::KbOrcaWhirlpoolsDecodedEvent::Swap(_) => {
panic!("unexpected swap event")
}
},
}
}
@@ -711,10 +675,10 @@ mod tests {
Some("So11111111111111111111111111111111111111112".to_string())
);
assert!(event.used_v2);
}
},
crate::KbOrcaWhirlpoolsDecodedEvent::CreatePool(_) => {
panic!("unexpected create event")
}
},
}
}
}

View File

@@ -80,7 +80,7 @@ pub struct KbPumpFunDecoder;
impl KbPumpFunDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Pump.fun events.
@@ -97,7 +97,7 @@ impl KbPumpFunDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
if transaction.err_json.is_some() {
return Ok(std::vec::Vec::new());
@@ -111,7 +111,7 @@ impl KbPumpFunDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let has_create_v2_log = kb_log_messages_contain_keyword(&log_messages, "create_v2")
@@ -250,7 +250,7 @@ impl KbPumpFunDecoder {
},
));
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -271,8 +271,8 @@ fn kb_decode_optional_instruction_data(
};
let decode_result = bs58::decode(encoded.as_str()).into_vec();
match decode_result {
Ok(decoded) => Some(decoded),
Err(_) => None,
Ok(decoded) => return Some(decoded),
Err(_) => return None,
}
}
@@ -287,7 +287,7 @@ fn kb_instruction_data_starts_with(
if instruction_data.len() < discriminator.len() {
return false;
}
&instruction_data[0..discriminator.len()] == discriminator
return &instruction_data[0..discriminator.len()] == discriminator;
}
fn kb_extract_u64_argument(
@@ -304,7 +304,7 @@ fn kb_extract_u64_argument(
}
let mut bytes = [0u8; 8];
bytes.copy_from_slice(&instruction_data[offset..end]);
Some(u64::from_le_bytes(bytes).to_string())
return Some(u64::from_le_bytes(bytes).to_string());
}
fn kb_extract_log_messages(
@@ -332,7 +332,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -343,7 +343,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_parse_accounts_json(
@@ -357,7 +357,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -366,7 +366,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_extract_account(
@@ -376,7 +376,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_normalize_log_text(value: &str) -> std::string::String {
@@ -386,7 +386,7 @@ fn kb_normalize_log_text(value: &str) -> std::string::String {
normalized.push(character.to_ascii_lowercase());
}
}
normalized
return normalized;
}
#[cfg(test)]
@@ -416,7 +416,7 @@ mod tests {
.to_string(),
);
dto.id = Some(91);
dto
return dto;
}
fn make_instruction() -> crate::KbChainInstructionDto {
@@ -445,7 +445,7 @@ mod tests {
None,
);
dto.id = Some(17);
dto
return dto;
}
#[test]
@@ -470,13 +470,13 @@ mod tests {
Some("AssociatedBondingCurve111".to_string())
);
assert_eq!(event.creator, Some("Creator111".to_string()));
}
},
crate::KbPumpFunDecodedEvent::BuyTrade(_) => {
panic!("unexpected pump_fun buy trade event");
}
},
crate::KbPumpFunDecodedEvent::SellTrade(_) => {
panic!("unexpected pump_fun sell trade event");
}
},
}
}

View File

@@ -46,7 +46,7 @@ pub struct KbPumpSwapDecoder;
impl KbPumpSwapDecoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more PumpSwap events.
@@ -63,7 +63,7 @@ impl KbPumpSwapDecoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -74,7 +74,7 @@ impl KbPumpSwapDecoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let mut decoded_events = std::vec::Vec::new();
@@ -110,40 +110,20 @@ impl KbPumpSwapDecoder {
parsed_json.as_ref(),
&["pool", "poolAccount", "amm", "ammPool", "poolState"],
)
.or_else(|| kb_extract_account(&accounts, 0));
.or_else(|| return kb_extract_account(&accounts, 0));
let token_a_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenAMint",
"baseMint",
"mintA",
"coinMint",
"token0Mint",
"mint0",
],
&["tokenAMint", "baseMint", "mintA", "coinMint", "token0Mint", "mint0"],
)
.or_else(|| kb_extract_account(&accounts, 3));
.or_else(|| return kb_extract_account(&accounts, 3));
let token_b_mint = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"tokenBMint",
"quoteMint",
"mintB",
"pcMint",
"token1Mint",
"mint1",
],
&["tokenBMint", "quoteMint", "mintB", "pcMint", "token1Mint", "mint1"],
)
.or_else(|| kb_extract_account(&accounts, 4));
.or_else(|| return kb_extract_account(&accounts, 4));
let pool_v2 = kb_extract_string_by_candidate_keys(
parsed_json.as_ref(),
&[
"poolV2",
"pool_v2",
"ammV2",
"bondingCurveV2",
"bonding_curve_v2",
],
&["poolV2", "pool_v2", "ammV2", "bondingCurveV2", "bonding_curve_v2"],
);
let pool_base_token_account = kb_extract_account(&accounts, 7);
let pool_quote_token_account = kb_extract_account(&accounts, 8);
@@ -200,7 +180,7 @@ impl KbPumpSwapDecoder {
));
}
}
Ok(decoded_events)
return Ok(decoded_events);
}
}
@@ -230,7 +210,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages;
}
fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword: &str) -> bool {
@@ -241,7 +221,7 @@ fn kb_log_messages_contain_keyword(log_messages: &[std::string::String], keyword
return true;
}
}
false
return false;
}
fn kb_parse_accounts_json(
@@ -255,7 +235,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -264,7 +244,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts);
}
fn kb_extract_account(
@@ -274,7 +254,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone());
}
fn kb_parse_optional_parsed_json(
@@ -286,11 +266,13 @@ fn kb_parse_optional_parsed_json(
};
let value_result = serde_json::from_str::<serde_json::Value>(parsed_json.as_str());
match value_result {
Ok(value) => Ok(Some(value)),
Err(error) => Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
))),
Ok(value) => return Ok(Some(value)),
Err(error) => {
return Err(crate::KbError::Json(format!(
"cannot parse instruction parsed_json '{}': {}",
parsed_json, error
)));
},
}
}
@@ -302,7 +284,7 @@ fn kb_extract_string_by_candidate_keys(
Some(value) => value,
None => return None,
};
kb_extract_string_by_candidate_keys_inner(value, candidate_keys)
return kb_extract_string_by_candidate_keys_inner(value, candidate_keys);
}
fn kb_extract_string_by_candidate_keys_inner(
@@ -337,7 +319,7 @@ fn kb_extract_string_by_candidate_keys_inner(
}
}
}
None
return None;
}
#[cfg(test)]
@@ -367,7 +349,7 @@ mod tests {
.to_string(),
);
dto.id = Some(92);
dto
return dto;
}
fn make_instruction() -> crate::KbChainInstructionDto {
@@ -389,7 +371,8 @@ mod tests {
"UserQuoteAta111",
"PoolBaseVault111",
"PoolQuoteVault111"
]).to_string(),
])
.to_string(),
None,
None,
Some(
@@ -405,7 +388,7 @@ mod tests {
),
);
dto.id = Some(18);
dto
return dto;
}
#[test]
@@ -436,10 +419,10 @@ mod tests {
Some(&serde_json::Value::String("PoolQuoteVault111".to_string()))
);
assert_eq!(event.trade_side, crate::KbSwapTradeSide::BuyBase);
}
},
crate::KbPumpSwapDecodedEvent::SellTrade(_) => {
panic!("unexpected sell event")
}
},
}
}

View File

@@ -44,7 +44,7 @@ pub struct KbRaydiumAmmV4Decoder;
impl KbRaydiumAmmV4Decoder {
/// Creates a new decoder.
pub fn new() -> Self {
Self
return Self;
}
/// Decodes one projected transaction into zero or more Raydium AmmV4 events.
@@ -61,7 +61,7 @@ impl KbRaydiumAmmV4Decoder {
"chain transaction '{}' has no internal id",
transaction.signature
)));
}
},
};
let transaction_json_result =
serde_json::from_str::<serde_json::Value>(transaction.transaction_json.as_str());
@@ -72,7 +72,7 @@ impl KbRaydiumAmmV4Decoder {
"cannot parse transaction_json for signature '{}': {}",
transaction.signature, error
)));
}
},
};
let log_messages = kb_extract_log_messages(&transaction_json);
let has_initialize2_log = kb_log_messages_contain_initialize2(&log_messages);
@@ -139,7 +139,7 @@ impl KbRaydiumAmmV4Decoder {
},
));
}
Ok(decoded_events)
return Ok(decoded_events)
}
}
@@ -168,7 +168,7 @@ fn kb_extract_log_messages(
messages.push(text.to_string());
}
}
messages
return messages
}
fn kb_log_messages_contain_initialize2(log_messages: &[std::string::String]) -> bool {
@@ -177,7 +177,7 @@ fn kb_log_messages_contain_initialize2(log_messages: &[std::string::String]) ->
return true;
}
}
false
return false
}
fn kb_parse_accounts_json(
@@ -191,7 +191,7 @@ fn kb_parse_accounts_json(
"cannot parse instruction accounts_json '{}': {}",
accounts_json, error
)));
}
},
};
let mut accounts = std::vec::Vec::new();
for value in values {
@@ -200,7 +200,7 @@ fn kb_parse_accounts_json(
accounts.push(text.to_string());
}
}
Ok(accounts)
return Ok(accounts)
}
fn kb_extract_account(
@@ -210,7 +210,7 @@ fn kb_extract_account(
if index >= accounts.len() {
return None;
}
Some(accounts[index].clone())
return Some(accounts[index].clone())
}
#[cfg(test)]
@@ -240,7 +240,7 @@ mod tests {
.to_string(),
);
dto.id = Some(42);
dto
return dto
}
fn make_instruction() -> crate::KbChainInstructionDto {
@@ -277,7 +277,7 @@ mod tests {
None,
);
dto.id = Some(7);
dto
return dto
}
#[test]
@@ -300,7 +300,7 @@ mod tests {
assert_eq!(event.token_a_mint, Some("TokenA111".to_string()));
assert_eq!(event.token_b_mint, Some("TokenB111".to_string()));
assert_eq!(event.market_account, Some("Market111".to_string()));
}
},
}
}

View File

@@ -20,28 +20,28 @@ impl KbRaydiumClmmDecodedEvent {
/// Returns the normalized event kind.
pub fn event_kind(&self) -> &'static str {
match self {
crate::KbRaydiumClmmDecodedEvent::SwapV2(_) => "raydium_clmm.swap_v2",
crate::KbRaydiumClmmDecodedEvent::SwapV2(_) => return "raydium_clmm.swap_v2",
}
}
/// Returns the pool account.
pub fn pool_account(&self) -> &str {
match self {
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => event.pool_state.as_str(),
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => return event.pool_state.as_str(),
}
}
/// Returns the normalized base mint.
pub fn base_mint(&self) -> &str {
match self {
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => event.base_mint.as_str(),
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => return event.base_mint.as_str(),
}
}
/// Returns the normalized quote mint.
pub fn quote_mint(&self) -> &str {
match self {
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => event.quote_mint.as_str(),
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => return event.quote_mint.as_str(),
}
}
@@ -51,10 +51,10 @@ impl KbRaydiumClmmDecodedEvent {
crate::KbRaydiumClmmDecodedEvent::SwapV2(event) => {
let result = serde_json::to_string(event);
match result {
Ok(payload_json) => Some(payload_json),
Err(_) => None,
Ok(payload_json) => return Some(payload_json),
Err(_) => return None,
}
}
},
}
}
}
@@ -144,7 +144,7 @@ pub fn kb_decode_raydium_clmm_instruction(
None => return decoded,
};
decoded.push(crate::KbRaydiumClmmDecodedEvent::SwapV2(event));
decoded
return decoded;
}
fn kb_decode_swap_v2(
@@ -219,7 +219,7 @@ fn kb_decode_swap_v2(
quote_vault = input_vault.clone();
trade_side = "BuyBase".to_string();
}
Some(crate::KbRaydiumClmmSwapV2Decoded {
return Some(crate::KbRaydiumClmmSwapV2Decoded {
payer,
amm_config,
pool_state,
@@ -239,7 +239,7 @@ fn kb_decode_swap_v2(
other_amount_threshold,
sqrt_price_limit_x64: sqrt_price_limit_x64.to_string(),
is_base_input,
})
});
}
fn kb_clone_account(
@@ -248,8 +248,8 @@ fn kb_clone_account(
) -> std::option::Option<std::string::String> {
let account_option = accounts.get(index);
match account_option {
Some(account) => Some(account.clone()),
None => None,
Some(account) => return Some(account.clone()),
None => return None,
}
}
@@ -263,7 +263,7 @@ fn kb_read_discriminator(data: &[u8]) -> std::option::Option<[u8; 8]> {
bytes[index] = data[index];
index += 1;
}
Some(bytes)
return Some(bytes);
}
fn kb_read_u64_le(data: &[u8], offset: usize) -> std::option::Option<u64> {
@@ -276,7 +276,7 @@ fn kb_read_u64_le(data: &[u8], offset: usize) -> std::option::Option<u64> {
bytes[index] = data[offset + index];
index += 1;
}
Some(u64::from_le_bytes(bytes))
return Some(u64::from_le_bytes(bytes));
}
fn kb_read_u128_le(data: &[u8], offset: usize) -> std::option::Option<u128> {
@@ -289,7 +289,7 @@ fn kb_read_u128_le(data: &[u8], offset: usize) -> std::option::Option<u128> {
bytes[index] = data[offset + index];
index += 1;
}
Some(u128::from_le_bytes(bytes))
return Some(u128::from_le_bytes(bytes));
}
fn kb_read_bool(data: &[u8], offset: usize) -> std::option::Option<bool> {
@@ -297,9 +297,9 @@ fn kb_read_bool(data: &[u8], offset: usize) -> std::option::Option<bool> {
return None;
}
match data[offset] {
0 => Some(false),
1 => Some(true),
_ => None,
0 => return Some(false),
1 => return Some(true),
_ => return None,
}
}
@@ -349,13 +349,13 @@ fn kb_decode_base58(input: &str) -> std::option::Option<std::vec::Vec<u8>> {
for byte in bytes {
result.push(byte);
}
Some(result)
return Some(result);
}
#[cfg(test)]
mod tests {
fn sample_swap_v2_accounts_json() -> &'static str {
r#"[
return r#"[
"8NQ32SyFKD1d5kenq4oM8Da6C6J9TQSMW1uAgFRveEQr",
"A1BBtTYJd4i3xU8D6Tc2FzU6ZN4oXZWXKZnCxwbHXr8x",
"GUrRxvnWVQSnbcz1eP9D5BqXwPZtRhmrqVfm5wY9meWR",
@@ -371,7 +371,7 @@ mod tests {
"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
"8ovxZR2Gv9Mr73aoXLQYTMaZvHCSpnEohzgjVHQwmyHr",
"9MssDxndh2Rn8DmGWL94hXVv22zxfDYHV7tvzfPgcaWe"
]"#
]"#;
}
#[test]
@@ -388,48 +388,21 @@ mod tests {
events[0].pool_account(),
"GUrRxvnWVQSnbcz1eP9D5BqXwPZtRhmrqVfm5wY9meWR"
);
assert_eq!(
event.pool_state,
"GUrRxvnWVQSnbcz1eP9D5BqXwPZtRhmrqVfm5wY9meWR"
);
assert_eq!(
event.input_vault,
"AvRzvwpSVnxsinLGQS3vZLqkZxhXZDM8F2qKccAo7rSq"
);
assert_eq!(
event.output_vault,
"CTkc4xDrpzjWcFLC1cxmUZZjZLSRV46HZa8wu5eKTbuh"
);
assert_eq!(
event.input_vault_mint,
"CKvjP8FrZpaKXjASEtX2nEU9w7M4RKskfnLQbKJBodV"
);
assert_eq!(
event.output_vault_mint,
"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"
);
assert_eq!(
event.base_mint,
"7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"
);
assert_eq!(
event.quote_mint,
"CKvjP8FrZpaKXjASEtX2nEU9w7M4RKskfnLQbKJBodV"
);
assert_eq!(
event.base_vault,
"CTkc4xDrpzjWcFLC1cxmUZZjZLSRV46HZa8wu5eKTbuh"
);
assert_eq!(
event.quote_vault,
"AvRzvwpSVnxsinLGQS3vZLqkZxhXZDM8F2qKccAo7rSq"
);
assert_eq!(event.pool_state, "GUrRxvnWVQSnbcz1eP9D5BqXwPZtRhmrqVfm5wY9meWR");
assert_eq!(event.input_vault, "AvRzvwpSVnxsinLGQS3vZLqkZxhXZDM8F2qKccAo7rSq");
assert_eq!(event.output_vault, "CTkc4xDrpzjWcFLC1cxmUZZjZLSRV46HZa8wu5eKTbuh");
assert_eq!(event.input_vault_mint, "CKvjP8FrZpaKXjASEtX2nEU9w7M4RKskfnLQbKJBodV");
assert_eq!(event.output_vault_mint, "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs");
assert_eq!(event.base_mint, "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs");
assert_eq!(event.quote_mint, "CKvjP8FrZpaKXjASEtX2nEU9w7M4RKskfnLQbKJBodV");
assert_eq!(event.base_vault, "CTkc4xDrpzjWcFLC1cxmUZZjZLSRV46HZa8wu5eKTbuh");
assert_eq!(event.quote_vault, "AvRzvwpSVnxsinLGQS3vZLqkZxhXZDM8F2qKccAo7rSq");
assert_eq!(event.trade_side, "BuyBase");
assert_eq!(event.amount, 148441657491969);
assert_eq!(event.other_amount_threshold, 0);
assert_eq!(event.sqrt_price_limit_x64, "0");
assert_eq!(event.is_base_input, true);
}
assert!(event.is_base_input);
},
}
}
@@ -476,15 +449,7 @@ mod tests {
#[test]
fn ignores_legacy_swap_for_now() {
let mut data = std::vec::Vec::<u8>::new();
data.push(248);
data.push(198);
data.push(158);
data.push(145);
data.push(225);
data.push(117);
data.push(135);
data.push(200);
let mut data: std::vec::Vec<u8> = vec![248, 198, 158, 145, 225, 117, 135, 200];
while data.len() < 41 {
data.push(0);
}

View File

@@ -91,32 +91,32 @@ impl KbRaydiumCpmmDecodedEvent {
/// Returns the storage event kind.
pub fn event_kind(&self) -> &'static str {
match self {
KbRaydiumCpmmDecodedEvent::SwapBaseInput(_) => "raydium_cpmm.swap_base_input",
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(_) => "raydium_cpmm.swap_base_output",
KbRaydiumCpmmDecodedEvent::SwapBaseInput(_) => return "raydium_cpmm.swap_base_input",
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(_) => return "raydium_cpmm.swap_base_output",
}
}
/// Returns the pool account.
pub fn pool_account(&self) -> &str {
match self {
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => event.pool_state.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => event.pool_state.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => return event.pool_state.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => return event.pool_state.as_str(),
}
}
/// Returns the normalized base mint.
pub fn base_mint(&self) -> &str {
match self {
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => event.base_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => event.base_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => return event.base_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => return event.base_mint.as_str(),
}
}
/// Returns the normalized quote mint.
pub fn quote_mint(&self) -> &str {
match self {
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => event.quote_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => event.quote_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => return event.quote_mint.as_str(),
KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => return event.quote_mint.as_str(),
}
}
@@ -126,17 +126,17 @@ impl KbRaydiumCpmmDecodedEvent {
crate::KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => {
let result = serde_json::to_string(event);
match result {
Ok(payload) => Some(payload),
Err(_) => None,
Ok(payload) => return Some(payload),
Err(_) => return None,
}
}
},
crate::KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => {
let result = serde_json::to_string(event);
match result {
Ok(payload) => Some(payload),
Err(_) => None,
Ok(payload) => return Some(payload),
Err(_) => return None,
}
}
},
}
}
}
@@ -161,9 +161,7 @@ pub fn kb_decode_raydium_cpmm_instruction(
if data.len() < 24 {
return std::vec::Vec::new();
}
let discriminator = [
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
];
let discriminator = [data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]];
if discriminator == KB_RAYDIUM_CPMM_SWAP_BASE_INPUT_DISCRIMINATOR {
let amount_in = match kb_read_u64_le(data.as_slice(), 8) {
Some(value) => value,
@@ -208,7 +206,7 @@ pub fn kb_decode_raydium_cpmm_instruction(
};
return vec![KbRaydiumCpmmDecodedEvent::SwapBaseOutput(swap)];
}
std::vec::Vec::new()
return std::vec::Vec::new();
}
fn kb_build_raydium_cpmm_swap(
@@ -233,12 +231,8 @@ fn kb_build_raydium_cpmm_swap(
output_vault.as_str(),
);
let input_is_base = normalized.input_is_base;
let trade_side = if input_is_base {
"sell".to_string()
} else {
"buy".to_string()
};
Some(KbRaydiumCpmmSwapDecoded {
let trade_side = if input_is_base { "sell".to_string() } else { "buy".to_string() };
return Some(KbRaydiumCpmmSwapDecoded {
swap_mode,
payer: accounts[0].clone(),
authority: accounts[1].clone(),
@@ -263,7 +257,7 @@ fn kb_build_raydium_cpmm_swap(
minimum_amount_out_raw,
max_amount_in_raw,
amount_out_raw,
})
});
}
struct KbRaydiumCpmmNormalizedPair {
@@ -307,13 +301,13 @@ fn kb_normalize_raydium_cpmm_pair(
input_is_base: true,
};
}
KbRaydiumCpmmNormalizedPair {
return KbRaydiumCpmmNormalizedPair {
base_mint: output_mint.to_string(),
quote_mint: input_mint.to_string(),
base_vault: output_vault.to_string(),
quote_vault: input_vault.to_string(),
input_is_base: false,
}
};
}
fn kb_is_quote_mint(mint: &str) -> bool {
@@ -329,7 +323,7 @@ fn kb_is_quote_mint(mint: &str) -> bool {
if mint == "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB" {
return true;
}
false
return false;
}
fn kb_parse_accounts_json(
@@ -337,16 +331,15 @@ fn kb_parse_accounts_json(
) -> std::option::Option<std::vec::Vec<std::string::String>> {
let result = serde_json::from_str::<std::vec::Vec<std::string::String>>(accounts_json);
match result {
Ok(accounts) => Some(accounts),
Err(_) => None,
Ok(accounts) => return Some(accounts),
Err(_) => return None,
}
}
fn kb_parse_data_json_as_base58(data_json: &str) -> std::option::Option<std::string::String> {
let json_string_result = serde_json::from_str::<std::string::String>(data_json);
match json_string_result {
Ok(value) => return Some(value),
Err(_) => {}
if let Ok(value) = json_string_result {
return Some(value);
}
let trimmed = data_json.trim();
if trimmed.is_empty() {
@@ -356,7 +349,7 @@ fn kb_parse_data_json_as_base58(data_json: &str) -> std::option::Option<std::str
if without_quotes.is_empty() {
return None;
}
Some(without_quotes.to_string())
return Some(without_quotes.to_string());
}
fn kb_read_u64_le(data: &[u8], offset: usize) -> std::option::Option<u64> {
@@ -373,7 +366,7 @@ fn kb_read_u64_le(data: &[u8], offset: usize) -> std::option::Option<u64> {
data[offset + 6],
data[offset + 7],
];
Some(u64::from_le_bytes(bytes))
return Some(u64::from_le_bytes(bytes));
}
#[cfg(test)]
@@ -402,26 +395,17 @@ mod tests {
assert_eq!(events.len(), 1);
match &events[0] {
crate::KbRaydiumCpmmDecodedEvent::SwapBaseInput(event) => {
assert_eq!(
event.pool_state,
"2ErXvV1tKtG3wiHqdofDjMou7Jusdsfasvfh8HrTj5oV"
);
assert_eq!(
event.base_mint,
"Pf9aSicGu3g6tTUBqrRbjNsGape9HopibspX5KSbonk"
);
assert_eq!(
event.quote_mint,
"USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"
);
assert_eq!(event.input_is_base, true);
assert_eq!(event.pool_state, "2ErXvV1tKtG3wiHqdofDjMou7Jusdsfasvfh8HrTj5oV");
assert_eq!(event.base_mint, "Pf9aSicGu3g6tTUBqrRbjNsGape9HopibspX5KSbonk");
assert_eq!(event.quote_mint, "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB");
assert!(event.input_is_base);
assert_eq!(event.trade_side, "sell");
assert_eq!(event.amount_in_raw.is_some(), true);
assert_eq!(event.minimum_amount_out_raw.is_some(), true);
}
assert!(event.amount_in_raw.is_some());
assert!(event.minimum_amount_out_raw.is_some());
},
_ => {
panic!("expected swap base input");
}
},
}
}
#[test]
@@ -448,26 +432,17 @@ mod tests {
assert_eq!(events.len(), 1);
match &events[0] {
crate::KbRaydiumCpmmDecodedEvent::SwapBaseOutput(event) => {
assert_eq!(
event.pool_state,
"2ErXvV1tKtG3wiHqdofDjMou7Jusdsfasvfh8HrTj5oV"
);
assert_eq!(
event.base_mint,
"Pf9aSicGu3g6tTUBqrRbjNsGape9HopibspX5KSbonk"
);
assert_eq!(
event.quote_mint,
"USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"
);
assert_eq!(event.input_is_base, false);
assert_eq!(event.pool_state, "2ErXvV1tKtG3wiHqdofDjMou7Jusdsfasvfh8HrTj5oV");
assert_eq!(event.base_mint, "Pf9aSicGu3g6tTUBqrRbjNsGape9HopibspX5KSbonk");
assert_eq!(event.quote_mint, "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB");
assert!(!event.input_is_base);
assert_eq!(event.trade_side, "buy");
assert_eq!(event.max_amount_in_raw.is_some(), true);
assert_eq!(event.amount_out_raw.is_some(), true);
}
assert!(event.max_amount_in_raw.is_some());
assert!(event.amount_out_raw.is_some());
},
_ => {
panic!("expected swap base output");
}
},
}
}
}