174 lines
5.7 KiB
Rust
174 lines
5.7 KiB
Rust
// file: kb_lib/src/db/queries/instruction_observation.rs
|
|
|
|
//! Queries for `k_sol_instruction_observations`.
|
|
|
|
/// Upserts one instruction observation row.
|
|
pub async fn query_instruction_observations_upsert(
|
|
database: &crate::Database,
|
|
dto: &crate::InstructionObservationDto,
|
|
) -> Result<i64, crate::Error> {
|
|
match database.connection() {
|
|
crate::DatabaseConnection::Sqlite(pool) => {
|
|
let query_result = sqlx::query(
|
|
r#"
|
|
INSERT INTO k_sol_instruction_observations (
|
|
observation_key,
|
|
transaction_id,
|
|
signature,
|
|
slot,
|
|
block_time,
|
|
failed,
|
|
instruction_id,
|
|
parent_instruction_id,
|
|
instruction_index,
|
|
inner_instruction_index,
|
|
program_id,
|
|
decoder_code,
|
|
discriminator_hex,
|
|
instruction_name,
|
|
accounts_json,
|
|
data_json,
|
|
pool_account,
|
|
decoded_event_kind,
|
|
decoded_event_id,
|
|
observed_at,
|
|
updated_at
|
|
)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(observation_key) DO UPDATE SET
|
|
transaction_id = excluded.transaction_id,
|
|
signature = excluded.signature,
|
|
slot = excluded.slot,
|
|
block_time = excluded.block_time,
|
|
failed = excluded.failed,
|
|
instruction_id = excluded.instruction_id,
|
|
parent_instruction_id = excluded.parent_instruction_id,
|
|
instruction_index = excluded.instruction_index,
|
|
inner_instruction_index = excluded.inner_instruction_index,
|
|
program_id = excluded.program_id,
|
|
decoder_code = excluded.decoder_code,
|
|
discriminator_hex = excluded.discriminator_hex,
|
|
instruction_name = excluded.instruction_name,
|
|
accounts_json = excluded.accounts_json,
|
|
data_json = excluded.data_json,
|
|
pool_account = excluded.pool_account,
|
|
decoded_event_kind = excluded.decoded_event_kind,
|
|
decoded_event_id = excluded.decoded_event_id,
|
|
updated_at = excluded.updated_at
|
|
"#,
|
|
)
|
|
.bind(dto.observation_key.clone())
|
|
.bind(dto.transaction_id)
|
|
.bind(dto.signature.clone())
|
|
.bind(dto.slot)
|
|
.bind(dto.block_time)
|
|
.bind(if dto.failed { 1_i64 } else { 0_i64 })
|
|
.bind(dto.instruction_id)
|
|
.bind(dto.parent_instruction_id)
|
|
.bind(dto.instruction_index)
|
|
.bind(dto.inner_instruction_index)
|
|
.bind(dto.program_id.clone())
|
|
.bind(dto.decoder_code.clone())
|
|
.bind(dto.discriminator_hex.clone())
|
|
.bind(dto.instruction_name.clone())
|
|
.bind(dto.accounts_json.clone())
|
|
.bind(dto.data_json.clone())
|
|
.bind(dto.pool_account.clone())
|
|
.bind(dto.decoded_event_kind.clone())
|
|
.bind(dto.decoded_event_id)
|
|
.bind(dto.observed_at.to_rfc3339())
|
|
.bind(dto.updated_at.to_rfc3339())
|
|
.execute(pool)
|
|
.await;
|
|
let query_result = match query_result {
|
|
Ok(query_result) => query_result,
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot upsert k_sol_instruction_observations on sqlite: {}",
|
|
error
|
|
)));
|
|
},
|
|
};
|
|
return Ok(query_result.last_insert_rowid());
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Lists instruction observations by optional decoder/discriminator/instruction filters.
|
|
pub async fn query_instruction_observations_list_by_filter(
|
|
database: &crate::Database,
|
|
decoder_code: std::option::Option<&str>,
|
|
discriminator_hex: std::option::Option<&str>,
|
|
instruction_name: std::option::Option<&str>,
|
|
limit: u32,
|
|
) -> Result<std::vec::Vec<crate::InstructionObservationDto>, crate::Error> {
|
|
if limit == 0 {
|
|
return Ok(std::vec::Vec::new());
|
|
}
|
|
match database.connection() {
|
|
crate::DatabaseConnection::Sqlite(pool) => {
|
|
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::InstructionObservationEntity>(
|
|
r#"
|
|
SELECT
|
|
id,
|
|
observation_key,
|
|
transaction_id,
|
|
signature,
|
|
slot,
|
|
block_time,
|
|
failed,
|
|
instruction_id,
|
|
parent_instruction_id,
|
|
instruction_index,
|
|
inner_instruction_index,
|
|
program_id,
|
|
decoder_code,
|
|
discriminator_hex,
|
|
instruction_name,
|
|
accounts_json,
|
|
data_json,
|
|
pool_account,
|
|
decoded_event_kind,
|
|
decoded_event_id,
|
|
observed_at,
|
|
updated_at
|
|
FROM k_sol_instruction_observations
|
|
WHERE (? IS NULL OR decoder_code = ?)
|
|
AND (? IS NULL OR discriminator_hex = ?)
|
|
AND (? IS NULL OR instruction_name = ?)
|
|
ORDER BY slot DESC, transaction_id DESC, instruction_id ASC
|
|
LIMIT ?
|
|
"#,
|
|
)
|
|
.bind(decoder_code.map(str::to_string))
|
|
.bind(decoder_code.map(str::to_string))
|
|
.bind(discriminator_hex.map(str::to_string))
|
|
.bind(discriminator_hex.map(str::to_string))
|
|
.bind(instruction_name.map(str::to_string))
|
|
.bind(instruction_name.map(str::to_string))
|
|
.bind(i64::from(limit))
|
|
.fetch_all(pool)
|
|
.await;
|
|
let entities = match query_result {
|
|
Ok(entities) => entities,
|
|
Err(error) => {
|
|
return Err(crate::Error::Db(format!(
|
|
"cannot list k_sol_instruction_observations on sqlite: {}",
|
|
error
|
|
)));
|
|
},
|
|
};
|
|
let mut dtos = std::vec::Vec::new();
|
|
for entity in entities {
|
|
let dto_result = crate::InstructionObservationDto::try_from(entity);
|
|
let dto = match dto_result {
|
|
Ok(dto) => dto,
|
|
Err(error) => return Err(error),
|
|
};
|
|
dtos.push(dto);
|
|
}
|
|
return Ok(dtos);
|
|
},
|
|
}
|
|
}
|