0.7.51
This commit is contained in:
@@ -523,43 +523,16 @@ impl DexDecodeService {
|
||||
transaction_id: i64,
|
||||
discriminator_hex: &str,
|
||||
) -> Result<(), crate::Error> {
|
||||
match self.database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let delete_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND protocol_name = 'raydium_clmm'
|
||||
AND event_kind = 'raydium_clmm.instruction_audit'
|
||||
AND (
|
||||
json_extract(payload_json, '$.discriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.instructionDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.instruction_discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.anchorEventDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.anchor_event_discriminator_hex') = ?
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete Raydium CLMM residual instruction audit '{}': {}",
|
||||
discriminator_hex, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
let delete_result =
|
||||
crate::query_dex_decoded_events_delete_raydium_clmm_instruction_audit_by_discriminator(
|
||||
self.database.as_ref(),
|
||||
transaction_id,
|
||||
discriminator_hex,
|
||||
)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,88 +679,18 @@ WHERE transaction_id = ?
|
||||
Some(audit_event_kind) => audit_event_kind,
|
||||
None => return Ok(()),
|
||||
};
|
||||
match self.database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let unlink_result = sqlx::query(
|
||||
r#"
|
||||
UPDATE k_sol_instruction_observations
|
||||
SET decoded_event_id = NULL
|
||||
WHERE decoded_event_id IN (
|
||||
SELECT id
|
||||
FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND protocol_name = ?
|
||||
AND event_kind = ?
|
||||
AND (
|
||||
json_extract(payload_json, '$.discriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.instructionDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.instruction_discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.anchorEventDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.anchor_event_discriminator_hex') = ?
|
||||
OR instr(lower(COALESCE(payload_json, '')), lower(?)) > 0
|
||||
)
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(protocol_name.to_string())
|
||||
.bind(audit_event_kind.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
if let Err(error) = unlink_result {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot unlink replaced instruction audit observation by discriminator on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
|
||||
let delete_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND protocol_name = ?
|
||||
AND event_kind = ?
|
||||
AND (
|
||||
json_extract(payload_json, '$.discriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.instructionDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.instruction_discriminator_hex') = ?
|
||||
OR json_extract(payload_json, '$.anchorEventDiscriminatorHex') = ?
|
||||
OR json_extract(payload_json, '$.anchor_event_discriminator_hex') = ?
|
||||
OR instr(lower(COALESCE(payload_json, '')), lower(?)) > 0
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(protocol_name.to_string())
|
||||
.bind(audit_event_kind.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.bind(discriminator_hex.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete replaced instruction audit by discriminator on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
let delete_result =
|
||||
crate::query_dex_decoded_events_delete_instruction_audit_by_discriminator(
|
||||
self.database.as_ref(),
|
||||
transaction_id,
|
||||
protocol_name,
|
||||
audit_event_kind,
|
||||
discriminator_hex,
|
||||
)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,34 +700,17 @@ WHERE transaction_id = ?
|
||||
_instruction_id: i64,
|
||||
anchor_event_discriminator_hex: &str,
|
||||
) -> Result<(), crate::Error> {
|
||||
match self.database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let delete_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND protocol_name = 'raydium_launchpad'
|
||||
AND event_kind = 'raydium_launchpad.instruction_audit'
|
||||
AND json_extract(payload_json, '$.anchorSelfCpiLog') = 1
|
||||
AND json_extract(payload_json, '$.anchorSelfCpiLogSelectorHex') = ?
|
||||
AND json_extract(payload_json, '$.anchorEventDiscriminatorHex') = ?
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX.to_string())
|
||||
.bind(anchor_event_discriminator_hex.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete replaced Raydium Launchpad self-CPI instruction audit on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
let delete_result =
|
||||
crate::query_dex_decoded_events_delete_raydium_launchpad_anchor_self_cpi_audit(
|
||||
self.database.as_ref(),
|
||||
transaction_id,
|
||||
METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX,
|
||||
anchor_event_discriminator_hex,
|
||||
)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,50 +722,16 @@ WHERE transaction_id = ?
|
||||
Some(transaction_id) => transaction_id,
|
||||
None => return Ok(()),
|
||||
};
|
||||
match self.database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let delete_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE id IN (
|
||||
SELECT audit.id
|
||||
FROM k_sol_dex_decoded_events audit
|
||||
WHERE audit.transaction_id = ?
|
||||
AND audit.protocol_name = 'raydium_launchpad'
|
||||
AND audit.event_kind = 'raydium_launchpad.instruction_audit'
|
||||
AND json_extract(audit.payload_json, '$.anchorSelfCpiLog') = 1
|
||||
AND json_extract(audit.payload_json, '$.anchorSelfCpiLogSelectorHex') = ?
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM k_sol_dex_decoded_events direct
|
||||
WHERE direct.transaction_id = audit.transaction_id
|
||||
AND direct.protocol_name = 'raydium_launchpad'
|
||||
AND direct.event_kind IN (
|
||||
'raydium_launchpad.trade_event',
|
||||
'raydium_launchpad.pool_create_event',
|
||||
'raydium_launchpad.claim_vested_event',
|
||||
'raydium_launchpad.create_vesting_event'
|
||||
let cleanup_result =
|
||||
crate::query_dex_decoded_events_cleanup_raydium_launchpad_anchor_self_cpi_audits(
|
||||
self.database.as_ref(),
|
||||
transaction_id,
|
||||
METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX,
|
||||
)
|
||||
AND json_extract(direct.payload_json, '$.anchorEventDiscriminatorHex') =
|
||||
json_extract(audit.payload_json, '$.anchorEventDiscriminatorHex')
|
||||
)
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
match delete_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot cleanup replaced Raydium Launchpad self-CPI instruction audits for signature '{}': {}",
|
||||
transaction.signature, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
.await;
|
||||
match cleanup_result {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1518,7 +1370,7 @@ WHERE id IN (
|
||||
event.instruction_id,
|
||||
"raydium_amm_v4",
|
||||
event.program_id.clone(),
|
||||
"raydium_amm_v4.swap",
|
||||
event.event_kind.as_str(),
|
||||
Some(event.pool_account.clone()),
|
||||
None,
|
||||
Some(event.token_a_mint.clone()),
|
||||
@@ -1528,6 +1380,24 @@ WHERE id IN (
|
||||
)
|
||||
.await;
|
||||
},
|
||||
crate::RaydiumAmmV4DecodedEvent::Instruction(event) => {
|
||||
return self
|
||||
.materialize_named_dex_event(
|
||||
transaction,
|
||||
event.transaction_id,
|
||||
event.instruction_id,
|
||||
"raydium_amm_v4",
|
||||
event.program_id.clone(),
|
||||
event.event_kind.as_str(),
|
||||
event.pool_account.clone(),
|
||||
event.market_account.clone(),
|
||||
event.token_a_mint.clone(),
|
||||
event.token_b_mint.clone(),
|
||||
event.lp_mint.clone(),
|
||||
event.payload_json.clone(),
|
||||
)
|
||||
.await;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,7 +1848,11 @@ WHERE id IN (
|
||||
let accounts = parse_instruction_accounts_vec(instruction.accounts_json.as_str());
|
||||
let data_base58 = parse_instruction_data_base58(instruction.data_json.as_deref());
|
||||
let data_bytes = instruction_data_bytes_from_base58(data_base58.as_deref());
|
||||
let discriminator_hex = discriminator_hex_from_bytes(data_bytes.as_deref(), 0);
|
||||
let discriminator_hex = raydium_instruction_discriminator_hex(
|
||||
audit_spec.protocol_name,
|
||||
data_bytes.as_deref(),
|
||||
0,
|
||||
);
|
||||
let anchor_event_spec = raydium_launchpad_anchor_self_cpi_event_spec(
|
||||
audit_spec.protocol_name,
|
||||
data_bytes.as_deref(),
|
||||
@@ -2598,6 +2472,17 @@ enum RaydiumMappedNonTradeAmountLayout {
|
||||
CpmmPoolStatus,
|
||||
CpmmWithdraw,
|
||||
LaunchpadInitialize,
|
||||
AmmV4Initialize,
|
||||
AmmV4Initialize2,
|
||||
AmmV4MonitorStep,
|
||||
AmmV4Deposit,
|
||||
AmmV4Withdraw,
|
||||
AmmV4SetParams,
|
||||
AmmV4WithdrawSrm,
|
||||
AmmV4PreInitialize,
|
||||
AmmV4SimulateInfo,
|
||||
AmmV4AdminCancelOrders,
|
||||
AmmV4UpdateConfigAccount,
|
||||
}
|
||||
|
||||
fn raydium_instruction_audit_spec(
|
||||
@@ -2649,6 +2534,9 @@ fn raydium_mapped_non_trade_instruction_spec(
|
||||
account_count,
|
||||
);
|
||||
}
|
||||
if protocol_name == "raydium_amm_v4" {
|
||||
return raydium_amm_v4_mapped_non_trade_instruction_spec(discriminator_hex, account_count);
|
||||
}
|
||||
if protocol_name == "raydium_clmm" {
|
||||
if discriminator_hex == "e445a52e51cb9a1d" {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
@@ -3173,6 +3061,198 @@ fn raydium_mapped_non_trade_instruction_spec(
|
||||
return None;
|
||||
}
|
||||
|
||||
fn raydium_amm_v4_mapped_non_trade_instruction_spec(
|
||||
discriminator_hex: &str,
|
||||
account_count: usize,
|
||||
) -> std::option::Option<RaydiumMappedNonTradeInstructionSpec> {
|
||||
match discriminator_hex {
|
||||
"00" => {
|
||||
if account_count >= 4 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "initialize",
|
||||
event_kind: "raydium_amm_v4.initialize",
|
||||
pool_account_index: Some(3),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4Initialize,
|
||||
});
|
||||
}
|
||||
},
|
||||
"01" => {
|
||||
if account_count >= 10 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "initialize2",
|
||||
event_kind: "raydium_amm_v4.initialize2_pool",
|
||||
pool_account_index: Some(4),
|
||||
token_a_mint_index: Some(8),
|
||||
token_b_mint_index: Some(9),
|
||||
lp_mint_index: Some(7),
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4Initialize2,
|
||||
});
|
||||
}
|
||||
},
|
||||
"02" => {
|
||||
if account_count >= 4 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "monitor_step",
|
||||
event_kind: "raydium_amm_v4.monitor_step",
|
||||
pool_account_index: Some(3),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4MonitorStep,
|
||||
});
|
||||
}
|
||||
},
|
||||
"03" => {
|
||||
if account_count >= 8 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "deposit",
|
||||
event_kind: "raydium_amm_v4.deposit",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: Some(5),
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4Deposit,
|
||||
});
|
||||
}
|
||||
},
|
||||
"04" => {
|
||||
if account_count >= 8 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "withdraw",
|
||||
event_kind: "raydium_amm_v4.withdraw",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: Some(5),
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4Withdraw,
|
||||
});
|
||||
}
|
||||
},
|
||||
"05" => {
|
||||
if account_count >= 4 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "migrate_to_open_book",
|
||||
event_kind: "raydium_amm_v4.migrate_to_open_book",
|
||||
pool_account_index: Some(3),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::None,
|
||||
});
|
||||
}
|
||||
},
|
||||
"06" => {
|
||||
if account_count >= 2 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "set_params",
|
||||
event_kind: "raydium_amm_v4.set_params",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4SetParams,
|
||||
});
|
||||
}
|
||||
},
|
||||
"07" => {
|
||||
if account_count >= 2 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "withdraw_pnl",
|
||||
event_kind: "raydium_amm_v4.withdraw_pnl",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::None,
|
||||
});
|
||||
}
|
||||
},
|
||||
"08" => {
|
||||
if account_count >= 2 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "withdraw_srm",
|
||||
event_kind: "raydium_amm_v4.withdraw_srm",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4WithdrawSrm,
|
||||
});
|
||||
}
|
||||
},
|
||||
"0a" => {
|
||||
if account_count >= 5 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "pre_initialize",
|
||||
event_kind: "raydium_amm_v4.pre_initialize",
|
||||
pool_account_index: Some(4),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4PreInitialize,
|
||||
});
|
||||
}
|
||||
},
|
||||
"0c" => {
|
||||
if account_count >= 2 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "simulate_info",
|
||||
event_kind: "raydium_amm_v4.simulate_info",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4SimulateInfo,
|
||||
});
|
||||
}
|
||||
},
|
||||
"0d" => {
|
||||
if account_count >= 2 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "admin_cancel_orders",
|
||||
event_kind: "raydium_amm_v4.admin_cancel_orders",
|
||||
pool_account_index: Some(1),
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4AdminCancelOrders,
|
||||
});
|
||||
}
|
||||
},
|
||||
"0e" => {
|
||||
if account_count >= 1 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "create_config_account",
|
||||
event_kind: "raydium_amm_v4.create_config_account",
|
||||
pool_account_index: None,
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::None,
|
||||
});
|
||||
}
|
||||
},
|
||||
"0f" => {
|
||||
if account_count >= 1 {
|
||||
return Some(RaydiumMappedNonTradeInstructionSpec {
|
||||
instruction_name: "update_config_account",
|
||||
event_kind: "raydium_amm_v4.update_config_account",
|
||||
pool_account_index: None,
|
||||
token_a_mint_index: None,
|
||||
token_b_mint_index: None,
|
||||
lp_mint_index: None,
|
||||
amount_layout: RaydiumMappedNonTradeAmountLayout::AmmV4UpdateConfigAccount,
|
||||
});
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
fn raydium_launchpad_mapped_non_trade_instruction_spec(
|
||||
discriminator_hex: &str,
|
||||
account_count: usize,
|
||||
@@ -3497,6 +3577,189 @@ fn insert_raydium_mapped_amounts(
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4Initialize => {
|
||||
if let Some(nonce) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"nonce".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(nonce as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(open_time) = read_u64_le_from_bytes(data, 2) {
|
||||
object.insert("openTime".to_string(), serde_json::Value::String(open_time.to_string()));
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4Initialize2 => {
|
||||
if let Some(nonce) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"nonce".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(nonce as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(open_time) = read_u64_le_from_bytes(data, 2) {
|
||||
object.insert("openTime".to_string(), serde_json::Value::String(open_time.to_string()));
|
||||
}
|
||||
if let Some(init_pc_amount) = read_u64_le_from_bytes(data, 10) {
|
||||
object.insert(
|
||||
"initPcAmount".to_string(),
|
||||
serde_json::Value::String(init_pc_amount.to_string()),
|
||||
);
|
||||
object.insert(
|
||||
"tokenBAmount".to_string(),
|
||||
serde_json::Value::String(init_pc_amount.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(init_coin_amount) = read_u64_le_from_bytes(data, 18) {
|
||||
object.insert(
|
||||
"initCoinAmount".to_string(),
|
||||
serde_json::Value::String(init_coin_amount.to_string()),
|
||||
);
|
||||
object.insert(
|
||||
"tokenAAmount".to_string(),
|
||||
serde_json::Value::String(init_coin_amount.to_string()),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4MonitorStep => {
|
||||
if let Some(plan_order_limit) = read_u16_le_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"planOrderLimit".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(plan_order_limit as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(place_order_limit) = read_u16_le_from_bytes(data, 3) {
|
||||
object.insert(
|
||||
"placeOrderLimit".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(place_order_limit as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(cancel_order_limit) = read_u16_le_from_bytes(data, 5) {
|
||||
object.insert(
|
||||
"cancelOrderLimit".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(cancel_order_limit as u64)),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4Deposit => {
|
||||
if let Some(max_coin_amount) = read_u64_le_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"maxCoinAmount".to_string(),
|
||||
serde_json::Value::String(max_coin_amount.to_string()),
|
||||
);
|
||||
object.insert(
|
||||
"tokenAAmount".to_string(),
|
||||
serde_json::Value::String(max_coin_amount.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(max_pc_amount) = read_u64_le_from_bytes(data, 9) {
|
||||
object.insert(
|
||||
"maxPcAmount".to_string(),
|
||||
serde_json::Value::String(max_pc_amount.to_string()),
|
||||
);
|
||||
object.insert(
|
||||
"tokenBAmount".to_string(),
|
||||
serde_json::Value::String(max_pc_amount.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(base_side) = read_u64_le_from_bytes(data, 17) {
|
||||
object.insert("baseSide".to_string(), serde_json::Value::String(base_side.to_string()));
|
||||
}
|
||||
if let Some(other_amount_min) = read_u64_le_from_bytes(data, 25) {
|
||||
object.insert(
|
||||
"otherAmountMin".to_string(),
|
||||
serde_json::Value::String(other_amount_min.to_string()),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4Withdraw => {
|
||||
if let Some(lp_amount) = read_u64_le_from_bytes(data, 1) {
|
||||
object.insert("lpAmountRaw".to_string(), serde_json::Value::String(lp_amount.to_string()));
|
||||
object.insert("liquidity".to_string(), serde_json::Value::String(lp_amount.to_string()));
|
||||
}
|
||||
if let Some(min_coin_amount) = read_u64_le_from_bytes(data, 9) {
|
||||
object.insert(
|
||||
"minCoinAmount".to_string(),
|
||||
serde_json::Value::String(min_coin_amount.to_string()),
|
||||
);
|
||||
}
|
||||
if let Some(min_pc_amount) = read_u64_le_from_bytes(data, 17) {
|
||||
object.insert(
|
||||
"minPcAmount".to_string(),
|
||||
serde_json::Value::String(min_pc_amount.to_string()),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4SetParams => {
|
||||
if let Some(param) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"configParam".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(param as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(value) = read_u64_le_from_bytes(data, 2) {
|
||||
object.insert("configValue".to_string(), serde_json::Value::String(value.to_string()));
|
||||
}
|
||||
if let Some(last_order_denominator) = read_u64_le_from_bytes(data, 10) {
|
||||
object.insert(
|
||||
"lastOrderDenominator".to_string(),
|
||||
serde_json::Value::String(last_order_denominator.to_string()),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4WithdrawSrm => {
|
||||
if let Some(amount) = read_u64_le_from_bytes(data, 1) {
|
||||
object.insert("amountRaw".to_string(), serde_json::Value::String(amount.to_string()));
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4PreInitialize => {
|
||||
object.insert("deprecatedInstruction".to_string(), serde_json::Value::Bool(true));
|
||||
object.insert("partialLifecycle".to_string(), serde_json::Value::Bool(true));
|
||||
object.insert(
|
||||
"skipCatalogReason".to_string(),
|
||||
serde_json::Value::String("missing_token_mints".to_string()),
|
||||
);
|
||||
if let Some(nonce) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"nonce".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(nonce as u64)),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4SimulateInfo => {
|
||||
if let Some(param) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"simulateParam".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(param as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(amount_in) = read_u64_le_from_bytes(data, 2) {
|
||||
object.insert("amountIn".to_string(), serde_json::Value::String(amount_in.to_string()));
|
||||
}
|
||||
if let Some(amount_out) = read_u64_le_from_bytes(data, 10) {
|
||||
object.insert("amountOutOrMinimumAmountOut".to_string(), serde_json::Value::String(amount_out.to_string()));
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4AdminCancelOrders => {
|
||||
if let Some(limit) = read_u16_le_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"orderCancelLimit".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(limit as u64)),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::AmmV4UpdateConfigAccount => {
|
||||
if let Some(param) = read_u8_from_bytes(data, 1) {
|
||||
object.insert(
|
||||
"configParam".to_string(),
|
||||
serde_json::Value::Number(serde_json::Number::from(param as u64)),
|
||||
);
|
||||
}
|
||||
if let Some(create_pool_fee) = read_u64_le_from_bytes(data, 2) {
|
||||
object.insert(
|
||||
"createPoolFee".to_string(),
|
||||
serde_json::Value::String(create_pool_fee.to_string()),
|
||||
);
|
||||
}
|
||||
},
|
||||
RaydiumMappedNonTradeAmountLayout::LaunchpadInitialize => {
|
||||
object.insert(
|
||||
"poolKindHint".to_string(),
|
||||
@@ -3555,6 +3818,19 @@ fn read_u8_from_bytes(data: &[u8], offset: usize) -> std::option::Option<u8> {
|
||||
return Some(data[offset]);
|
||||
}
|
||||
|
||||
fn read_u16_le_from_bytes(data: &[u8], offset: usize) -> std::option::Option<u16> {
|
||||
if data.len() < offset + 2 {
|
||||
return None;
|
||||
}
|
||||
let mut bytes = [0_u8; 2];
|
||||
let mut index = 0_usize;
|
||||
while index < 2 {
|
||||
bytes[index] = data[offset + index];
|
||||
index += 1;
|
||||
}
|
||||
return Some(u16::from_le_bytes(bytes));
|
||||
}
|
||||
|
||||
fn read_i32_le_from_bytes(data: &[u8], offset: usize) -> std::option::Option<i32> {
|
||||
if data.len() < offset + 4 {
|
||||
return None;
|
||||
@@ -3701,7 +3977,7 @@ fn build_meteora_instruction_audit_payload(
|
||||
};
|
||||
let data_base58 = parse_instruction_data_base58(instruction.data_json.as_deref());
|
||||
let data_bytes = instruction_data_bytes_from_base58(data_base58.as_deref());
|
||||
let discriminator_hex = discriminator_hex_from_bytes(data_bytes.as_deref(), 0);
|
||||
let discriminator_hex = raydium_instruction_discriminator_hex(protocol_name, data_bytes.as_deref(), 0);
|
||||
let anchor_self_cpi_log =
|
||||
discriminator_hex.as_deref() == Some(METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX);
|
||||
let anchor_event_discriminator_hex = if anchor_self_cpi_log {
|
||||
@@ -4239,7 +4515,7 @@ fn build_raydium_instruction_audit_payload(
|
||||
};
|
||||
let data_base58 = parse_instruction_data_base58(instruction.data_json.as_deref());
|
||||
let data_bytes = instruction_data_bytes_from_base58(data_base58.as_deref());
|
||||
let discriminator_hex = discriminator_hex_from_bytes(data_bytes.as_deref(), 0);
|
||||
let discriminator_hex = raydium_instruction_discriminator_hex(protocol_name, data_bytes.as_deref(), 0);
|
||||
let anchor_self_cpi_log =
|
||||
discriminator_hex.as_deref() == Some(METEORA_ANCHOR_SELF_CPI_LOG_SELECTOR_HEX);
|
||||
let anchor_event_discriminator_hex = if anchor_self_cpi_log {
|
||||
@@ -4438,6 +4714,40 @@ fn discriminator_hex_from_base58(
|
||||
return discriminator_hex_from_bytes(bytes.as_deref(), 0);
|
||||
}
|
||||
|
||||
fn raydium_instruction_discriminator_hex(
|
||||
protocol_name: &str,
|
||||
bytes: std::option::Option<&[u8]>,
|
||||
offset: usize,
|
||||
) -> std::option::Option<std::string::String> {
|
||||
if protocol_name == "raydium_amm_v4" {
|
||||
return discriminator_hex_from_bytes_with_len(bytes, offset, 1);
|
||||
}
|
||||
return discriminator_hex_from_bytes(bytes, offset);
|
||||
}
|
||||
|
||||
fn discriminator_hex_from_bytes_with_len(
|
||||
bytes: std::option::Option<&[u8]>,
|
||||
offset: usize,
|
||||
length: usize,
|
||||
) -> std::option::Option<std::string::String> {
|
||||
let bytes = match bytes {
|
||||
Some(bytes) => bytes,
|
||||
None => return None,
|
||||
};
|
||||
if bytes.len() < offset + length {
|
||||
return None;
|
||||
}
|
||||
let mut text = std::string::String::new();
|
||||
let mut index = offset;
|
||||
let end = offset + length;
|
||||
while index < end {
|
||||
let byte = bytes[index];
|
||||
text.push_str(format!("{byte:02x}").as_str());
|
||||
index += 1;
|
||||
}
|
||||
return Some(text);
|
||||
}
|
||||
|
||||
fn discriminator_hex_from_bytes(
|
||||
bytes: std::option::Option<&[u8]>,
|
||||
offset: usize,
|
||||
|
||||
Reference in New Issue
Block a user