0.7.25
This commit is contained in:
@@ -19,9 +19,7 @@ pub struct KbDatabase {
|
||||
|
||||
impl KbDatabase {
|
||||
/// Opens a database connection without initializing the schema.
|
||||
pub async fn connect(
|
||||
config: &crate::KbDatabaseConfig,
|
||||
) -> Result<Self, crate::KbError> {
|
||||
pub async fn connect(config: &crate::KbDatabaseConfig) -> Result<Self, crate::KbError> {
|
||||
if !config.enabled {
|
||||
return Err(crate::KbError::Config(
|
||||
"database is disabled in configuration".to_string(),
|
||||
@@ -40,11 +38,11 @@ impl KbDatabase {
|
||||
Ok(pool) => pool,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
backend: crate::KbDatabaseBackend::Sqlite,
|
||||
database_url,
|
||||
connection: KbDatabaseConnection::Sqlite(pool),
|
||||
})
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -64,47 +62,40 @@ impl KbDatabase {
|
||||
return Err(error);
|
||||
}
|
||||
}
|
||||
Ok(database)
|
||||
return Ok(database);
|
||||
}
|
||||
|
||||
/// Returns the configured backend.
|
||||
pub fn backend(
|
||||
&self,
|
||||
) -> crate::KbDatabaseBackend {
|
||||
self.backend
|
||||
pub fn backend(&self) -> crate::KbDatabaseBackend {
|
||||
return self.backend;
|
||||
}
|
||||
|
||||
/// Returns a displayable database URL-like string.
|
||||
pub fn database_url(
|
||||
&self,
|
||||
) -> &str {
|
||||
&self.database_url
|
||||
pub fn database_url(&self) -> &str {
|
||||
return &self.database_url;
|
||||
}
|
||||
|
||||
/// Pings the database.
|
||||
pub async fn ping(
|
||||
&self,
|
||||
) -> Result<(), crate::KbError> {
|
||||
pub async fn ping(&self) -> Result<(), crate::KbError> {
|
||||
match &self.connection {
|
||||
KbDatabaseConnection::Sqlite(pool) => {
|
||||
let ping_result = sqlx::query("SELECT 1").execute(pool).await;
|
||||
match ping_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot ping sqlite database '{}': {}",
|
||||
self.database_url,
|
||||
error
|
||||
))),
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot ping sqlite database '{}': {}",
|
||||
self.database_url, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the underlying connection enum.
|
||||
pub(crate) fn connection(
|
||||
&self,
|
||||
) -> &KbDatabaseConnection {
|
||||
&self.connection
|
||||
pub(crate) fn connection(&self) -> &KbDatabaseConnection {
|
||||
return &self.connection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ impl KbAnalysisSignalDto {
|
||||
score: std::option::Option<f64>,
|
||||
payload: serde_json::Value,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
signal_kind,
|
||||
severity,
|
||||
@@ -42,7 +42,7 @@ impl KbAnalysisSignalDto {
|
||||
score,
|
||||
payload,
|
||||
created_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ impl TryFrom<crate::KbAnalysisSignalEntity> for KbAnalysisSignalDto {
|
||||
"cannot parse analysis signal created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let payload_result = serde_json::from_str::<serde_json::Value>(&entity.payload_json);
|
||||
let payload = match payload_result {
|
||||
@@ -73,9 +73,9 @@ impl TryFrom<crate::KbAnalysisSignalEntity> for KbAnalysisSignalDto {
|
||||
"cannot parse analysis signal payload_json '{}': {}",
|
||||
entity.payload_json, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
signal_kind: entity.signal_kind,
|
||||
severity,
|
||||
@@ -84,6 +84,6 @@ impl TryFrom<crate::KbAnalysisSignalEntity> for KbAnalysisSignalDto {
|
||||
score: entity.score,
|
||||
payload,
|
||||
created_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ impl KbChainInstructionDto {
|
||||
parsed_type: std::option::Option<std::string::String>,
|
||||
parsed_json: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
transaction_id,
|
||||
parent_instruction_id,
|
||||
@@ -63,7 +63,7 @@ impl KbChainInstructionDto {
|
||||
parsed_type,
|
||||
parsed_json,
|
||||
created_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ impl TryFrom<crate::KbChainInstructionEntity> for KbChainInstructionDto {
|
||||
"cannot convert chain instruction instruction_index '{}' to u32: {}",
|
||||
entity.instruction_index, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let inner_instruction_index = match entity.inner_instruction_index {
|
||||
Some(inner_instruction_index) => {
|
||||
@@ -91,9 +91,9 @@ impl TryFrom<crate::KbChainInstructionEntity> for KbChainInstructionDto {
|
||||
"cannot convert chain instruction inner_instruction_index '{}' to u32: {}",
|
||||
inner_instruction_index, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let stack_height = match entity.stack_height {
|
||||
@@ -106,9 +106,9 @@ impl TryFrom<crate::KbChainInstructionEntity> for KbChainInstructionDto {
|
||||
"cannot convert chain instruction stack_height '{}' to u32: {}",
|
||||
stack_height, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at);
|
||||
@@ -119,9 +119,9 @@ impl TryFrom<crate::KbChainInstructionEntity> for KbChainInstructionDto {
|
||||
"cannot parse chain instruction created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
transaction_id: entity.transaction_id,
|
||||
parent_instruction_id: entity.parent_instruction_id,
|
||||
@@ -135,6 +135,6 @@ impl TryFrom<crate::KbChainInstructionEntity> for KbChainInstructionDto {
|
||||
parsed_type: entity.parsed_type,
|
||||
parsed_json: entity.parsed_json,
|
||||
created_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,13 @@ impl KbChainSlotDto {
|
||||
block_time_unix: std::option::Option<i64>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
slot,
|
||||
parent_slot,
|
||||
block_time_unix,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ impl TryFrom<crate::KbChainSlotEntity> for KbChainSlotDto {
|
||||
"cannot convert chain slot '{}' to u64: {}",
|
||||
entity.slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let parent_slot = match entity.parent_slot {
|
||||
Some(parent_slot) => {
|
||||
@@ -59,9 +59,9 @@ impl TryFrom<crate::KbChainSlotEntity> for KbChainSlotDto {
|
||||
"cannot convert chain parent_slot '{}' to u64: {}",
|
||||
parent_slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at);
|
||||
@@ -72,7 +72,7 @@ impl TryFrom<crate::KbChainSlotEntity> for KbChainSlotDto {
|
||||
"cannot parse chain slot created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -82,14 +82,14 @@ impl TryFrom<crate::KbChainSlotEntity> for KbChainSlotDto {
|
||||
"cannot parse chain slot updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
slot,
|
||||
parent_slot,
|
||||
block_time_unix: entity.block_time_unix,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ impl KbChainTransactionDto {
|
||||
transaction_json: std::string::String,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
signature,
|
||||
slot,
|
||||
@@ -55,7 +55,7 @@ impl KbChainTransactionDto {
|
||||
transaction_json,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,9 +73,9 @@ impl TryFrom<crate::KbChainTransactionEntity> for KbChainTransactionDto {
|
||||
"cannot convert chain transaction slot '{}' to u64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at);
|
||||
@@ -86,7 +86,7 @@ impl TryFrom<crate::KbChainTransactionEntity> for KbChainTransactionDto {
|
||||
"cannot parse chain transaction created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -96,9 +96,9 @@ impl TryFrom<crate::KbChainTransactionEntity> for KbChainTransactionDto {
|
||||
"cannot parse chain transaction updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
signature: entity.signature,
|
||||
slot,
|
||||
@@ -110,6 +110,6 @@ impl TryFrom<crate::KbChainTransactionEntity> for KbChainTransactionDto {
|
||||
transaction_json: entity.transaction_json,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ pub struct KbDbMetadataDto {
|
||||
impl KbDbMetadataDto {
|
||||
/// Creates a new metadata DTO with the current UTC timestamp.
|
||||
pub fn new(key: std::string::String, value: std::string::String) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
key,
|
||||
value,
|
||||
updated_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,22 +36,22 @@ impl TryFrom<crate::KbDbMetadataEntity> for KbDbMetadataDto {
|
||||
"cannot parse db metadata timestamp '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
key: entity.key,
|
||||
value: entity.value,
|
||||
updated_at: parsed.with_timezone(&chrono::Utc),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KbDbMetadataDto> for crate::KbDbMetadataEntity {
|
||||
fn from(dto: KbDbMetadataDto) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
key: dto.key,
|
||||
value: dto.value,
|
||||
updated_at: dto.updated_at.to_rfc3339(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ impl KbDbRuntimeEventDto {
|
||||
source: std::string::String,
|
||||
message: std::string::String,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
event_kind,
|
||||
level,
|
||||
source,
|
||||
message,
|
||||
created_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,20 +50,20 @@ impl TryFrom<crate::KbDbRuntimeEventEntity> for KbDbRuntimeEventDto {
|
||||
"cannot parse runtime event created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let level_result = crate::KbDbRuntimeEventLevel::from_i16(entity.level);
|
||||
let level = match level_result {
|
||||
Ok(level) => level,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
event_kind: entity.event_kind,
|
||||
level,
|
||||
source: entity.source,
|
||||
message: entity.message,
|
||||
created_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl KbDexDto {
|
||||
is_enabled: bool,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
code,
|
||||
name,
|
||||
@@ -42,7 +42,7 @@ impl KbDexDto {
|
||||
is_enabled,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl TryFrom<crate::KbDexEntity> for KbDexDto {
|
||||
"cannot parse dex created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -68,9 +68,9 @@ impl TryFrom<crate::KbDexEntity> for KbDexDto {
|
||||
"cannot parse dex updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
code: entity.code,
|
||||
name: entity.name,
|
||||
@@ -79,6 +79,6 @@ impl TryFrom<crate::KbDexEntity> for KbDexDto {
|
||||
is_enabled: entity.is_enabled != 0,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ impl KbDexDecodedEventDto {
|
||||
market_account: std::option::Option<std::string::String>,
|
||||
payload_json: std::string::String,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
transaction_id,
|
||||
instruction_id,
|
||||
@@ -63,7 +63,7 @@ impl KbDexDecodedEventDto {
|
||||
market_account,
|
||||
payload_json,
|
||||
created_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ impl TryFrom<crate::KbDexDecodedEventEntity> for KbDexDecodedEventDto {
|
||||
"cannot parse dex decoded event created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
transaction_id: entity.transaction_id,
|
||||
instruction_id: entity.instruction_id,
|
||||
@@ -95,6 +95,6 @@ impl TryFrom<crate::KbDexDecodedEventEntity> for KbDexDecodedEventDto {
|
||||
market_account: entity.market_account,
|
||||
payload_json: entity.payload_json,
|
||||
created_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ impl KbKnownHttpEndpointDto {
|
||||
enabled: bool,
|
||||
roles: std::vec::Vec<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
name,
|
||||
provider,
|
||||
url,
|
||||
@@ -38,7 +38,7 @@ impl KbKnownHttpEndpointDto {
|
||||
roles,
|
||||
last_seen_at: None,
|
||||
updated_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ impl TryFrom<crate::KbKnownHttpEndpointEntity> for KbKnownHttpEndpointDto {
|
||||
"cannot parse known http endpoint roles_json '{}': {}",
|
||||
entity.roles_json, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -65,7 +65,7 @@ impl TryFrom<crate::KbKnownHttpEndpointEntity> for KbKnownHttpEndpointDto {
|
||||
"cannot parse known http endpoint updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let last_seen_at = match entity.last_seen_at {
|
||||
Some(last_seen_at_text) => {
|
||||
@@ -77,12 +77,12 @@ impl TryFrom<crate::KbKnownHttpEndpointEntity> for KbKnownHttpEndpointDto {
|
||||
"cannot parse known http endpoint last_seen_at '{}': {}",
|
||||
last_seen_at_text, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
name: entity.name,
|
||||
provider: entity.provider,
|
||||
url: entity.url,
|
||||
@@ -90,7 +90,7 @@ impl TryFrom<crate::KbKnownHttpEndpointEntity> for KbKnownHttpEndpointDto {
|
||||
roles,
|
||||
last_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,16 +106,16 @@ impl TryFrom<KbKnownHttpEndpointDto> for crate::KbKnownHttpEndpointEntity {
|
||||
"cannot serialize known http endpoint roles: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
name: dto.name,
|
||||
provider: dto.provider,
|
||||
url: dto.url,
|
||||
enabled: if dto.enabled { 1 } else { 0 },
|
||||
roles_json,
|
||||
last_seen_at: dto.last_seen_at.map(|value| value.to_rfc3339()),
|
||||
last_seen_at: dto.last_seen_at.map(|value| return value.to_rfc3339()),
|
||||
updated_at: dto.updated_at.to_rfc3339(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ impl KbKnownWsEndpointDto {
|
||||
enabled: bool,
|
||||
roles: std::vec::Vec<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
name,
|
||||
provider,
|
||||
url,
|
||||
@@ -38,7 +38,7 @@ impl KbKnownWsEndpointDto {
|
||||
roles,
|
||||
last_seen_at: None,
|
||||
updated_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ impl TryFrom<crate::KbKnownWsEndpointEntity> for KbKnownWsEndpointDto {
|
||||
"cannot parse known ws endpoint roles_json '{}': {}",
|
||||
entity.roles_json, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -65,7 +65,7 @@ impl TryFrom<crate::KbKnownWsEndpointEntity> for KbKnownWsEndpointDto {
|
||||
"cannot parse known ws endpoint updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let last_seen_at = match entity.last_seen_at {
|
||||
Some(last_seen_at_text) => {
|
||||
@@ -77,12 +77,12 @@ impl TryFrom<crate::KbKnownWsEndpointEntity> for KbKnownWsEndpointDto {
|
||||
"cannot parse known ws endpoint last_seen_at '{}': {}",
|
||||
last_seen_at_text, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
name: entity.name,
|
||||
provider: entity.provider,
|
||||
url: entity.url,
|
||||
@@ -90,7 +90,7 @@ impl TryFrom<crate::KbKnownWsEndpointEntity> for KbKnownWsEndpointDto {
|
||||
roles,
|
||||
last_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,16 +106,16 @@ impl TryFrom<KbKnownWsEndpointDto> for crate::KbKnownWsEndpointEntity {
|
||||
"cannot serialize known ws endpoint roles: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
name: dto.name,
|
||||
provider: dto.provider,
|
||||
url: dto.url,
|
||||
enabled: if dto.enabled { 1 } else { 0 },
|
||||
roles_json,
|
||||
last_seen_at: dto.last_seen_at.map(|value| value.to_rfc3339()),
|
||||
last_seen_at: dto.last_seen_at.map(|value| return value.to_rfc3339()),
|
||||
updated_at: dto.updated_at.to_rfc3339(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ impl KbLaunchAttributionDto {
|
||||
matched_value: std::string::String,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
launch_surface_id,
|
||||
transaction_id,
|
||||
@@ -58,7 +58,7 @@ impl KbLaunchAttributionDto {
|
||||
matched_value,
|
||||
attributed_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ impl TryFrom<crate::KbLaunchAttributionEntity> for KbLaunchAttributionDto {
|
||||
"cannot parse launch_attribution attributed_at '{}': {}",
|
||||
entity.attributed_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -84,9 +84,9 @@ impl TryFrom<crate::KbLaunchAttributionEntity> for KbLaunchAttributionDto {
|
||||
"cannot parse launch_attribution updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
launch_surface_id: entity.launch_surface_id,
|
||||
transaction_id: entity.transaction_id,
|
||||
@@ -99,6 +99,6 @@ impl TryFrom<crate::KbLaunchAttributionEntity> for KbLaunchAttributionDto {
|
||||
matched_value: entity.matched_value,
|
||||
attributed_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ impl KbLaunchSurfaceDto {
|
||||
is_enabled: bool,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
code,
|
||||
name,
|
||||
@@ -38,7 +38,7 @@ impl KbLaunchSurfaceDto {
|
||||
is_enabled,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl TryFrom<crate::KbLaunchSurfaceEntity> for KbLaunchSurfaceDto {
|
||||
"cannot parse launch_surface created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -64,9 +64,9 @@ impl TryFrom<crate::KbLaunchSurfaceEntity> for KbLaunchSurfaceDto {
|
||||
"cannot parse launch_surface updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
code: entity.code,
|
||||
name: entity.name,
|
||||
@@ -74,6 +74,6 @@ impl TryFrom<crate::KbLaunchSurfaceEntity> for KbLaunchSurfaceDto {
|
||||
is_enabled: entity.is_enabled != 0,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ impl KbLaunchSurfaceKeyDto {
|
||||
match_value: std::string::String,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
launch_surface_id,
|
||||
match_kind,
|
||||
match_value,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ impl TryFrom<crate::KbLaunchSurfaceKeyEntity> for KbLaunchSurfaceKeyDto {
|
||||
"cannot parse launch_surface_key created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -60,15 +60,15 @@ impl TryFrom<crate::KbLaunchSurfaceKeyEntity> for KbLaunchSurfaceKeyDto {
|
||||
"cannot parse launch_surface_key updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
launch_surface_id: entity.launch_surface_id,
|
||||
match_kind: entity.match_kind,
|
||||
match_value: entity.match_value,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ impl KbLiquidityEventDto {
|
||||
quote_amount: std::string::String,
|
||||
lp_amount: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -74,7 +74,7 @@ impl KbLiquidityEventDto {
|
||||
quote_amount,
|
||||
lp_amount,
|
||||
executed_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ impl TryFrom<crate::KbLiquidityEventEntity> for KbLiquidityEventDto {
|
||||
"cannot parse liquidity event executed_at '{}': {}",
|
||||
entity.executed_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let slot = match entity.slot {
|
||||
Some(slot) => {
|
||||
@@ -107,12 +107,12 @@ impl TryFrom<crate::KbLiquidityEventEntity> for KbLiquidityEventDto {
|
||||
"cannot convert liquidity event slot '{}' to u64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -129,6 +129,6 @@ impl TryFrom<crate::KbLiquidityEventEntity> for KbLiquidityEventDto {
|
||||
quote_amount: entity.quote_amount,
|
||||
lp_amount: entity.lp_amount,
|
||||
executed_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ impl KbObservedTokenDto {
|
||||
status: crate::KbObservedTokenStatus,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
mint,
|
||||
symbol,
|
||||
@@ -49,16 +49,14 @@ impl KbObservedTokenDto {
|
||||
first_seen_at: now,
|
||||
last_seen_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
type Error = crate::KbError;
|
||||
|
||||
fn try_from(
|
||||
entity: crate::KbObservedTokenEntity,
|
||||
) -> Result<Self, Self::Error> {
|
||||
fn try_from(entity: crate::KbObservedTokenEntity) -> Result<Self, Self::Error> {
|
||||
let status_result = crate::KbObservedTokenStatus::from_i16(entity.status);
|
||||
let status = match status_result {
|
||||
Ok(status) => status,
|
||||
@@ -70,8 +68,7 @@ impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot parse observed token first_seen_at '{}': {}",
|
||||
entity.first_seen_at,
|
||||
error
|
||||
entity.first_seen_at, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
@@ -81,8 +78,7 @@ impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot parse observed token last_seen_at '{}': {}",
|
||||
entity.last_seen_at,
|
||||
error
|
||||
entity.last_seen_at, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
@@ -92,8 +88,7 @@ impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot parse observed token updated_at '{}': {}",
|
||||
entity.updated_at,
|
||||
error
|
||||
entity.updated_at, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
@@ -105,15 +100,14 @@ impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot convert observed token decimals '{}' to u8: {}",
|
||||
decimals,
|
||||
error
|
||||
decimals, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
mint: entity.mint,
|
||||
symbol: entity.symbol,
|
||||
@@ -124,6 +118,6 @@ impl TryFrom<crate::KbObservedTokenEntity> for KbObservedTokenDto {
|
||||
first_seen_at,
|
||||
last_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl KbOnchainObservationDto {
|
||||
slot: std::option::Option<u64>,
|
||||
payload: serde_json::Value,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
observation_kind,
|
||||
source_kind,
|
||||
@@ -42,7 +42,7 @@ impl KbOnchainObservationDto {
|
||||
slot,
|
||||
payload,
|
||||
observed_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ impl TryFrom<crate::KbOnchainObservationEntity> for KbOnchainObservationDto {
|
||||
"cannot parse on-chain observation observed_at '{}': {}",
|
||||
entity.observed_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let payload_result = serde_json::from_str::<serde_json::Value>(&entity.payload_json);
|
||||
let payload = match payload_result {
|
||||
@@ -73,7 +73,7 @@ impl TryFrom<crate::KbOnchainObservationEntity> for KbOnchainObservationDto {
|
||||
"cannot parse on-chain observation payload_json '{}': {}",
|
||||
entity.payload_json, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let slot = match entity.slot {
|
||||
Some(slot) => {
|
||||
@@ -85,12 +85,12 @@ impl TryFrom<crate::KbOnchainObservationEntity> for KbOnchainObservationDto {
|
||||
"cannot convert on-chain observation slot '{}' to u64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
observation_kind: entity.observation_kind,
|
||||
source_kind,
|
||||
@@ -99,6 +99,6 @@ impl TryFrom<crate::KbOnchainObservationEntity> for KbOnchainObservationDto {
|
||||
slot,
|
||||
payload,
|
||||
observed_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl KbPairDto {
|
||||
symbol: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -42,7 +42,7 @@ impl KbPairDto {
|
||||
symbol,
|
||||
first_seen_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl TryFrom<crate::KbPairEntity> for KbPairDto {
|
||||
"cannot parse pair first_seen_at '{}': {}",
|
||||
entity.first_seen_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -68,9 +68,9 @@ impl TryFrom<crate::KbPairEntity> for KbPairDto {
|
||||
"cannot parse pair updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -79,6 +79,6 @@ impl TryFrom<crate::KbPairEntity> for KbPairDto {
|
||||
symbol: entity.symbol,
|
||||
first_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ impl KbPairAnalyticSignalDto {
|
||||
last_transaction_id: std::option::Option<i64>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
pair_id,
|
||||
signal_kind,
|
||||
@@ -58,7 +58,7 @@ impl KbPairAnalyticSignalDto {
|
||||
last_transaction_id,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ impl TryFrom<crate::KbPairAnalyticSignalEntity> for KbPairAnalyticSignalDto {
|
||||
"cannot parse pair_analytic_signal signal_value_json '{}': {}",
|
||||
entity.signal_value_json, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let created_at_result = chrono::DateTime::parse_from_rfc3339(entity.created_at.as_str());
|
||||
let created_at = match created_at_result {
|
||||
@@ -90,7 +90,7 @@ impl TryFrom<crate::KbPairAnalyticSignalEntity> for KbPairAnalyticSignalDto {
|
||||
"cannot parse pair_analytic_signal created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(entity.updated_at.as_str());
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -100,9 +100,9 @@ impl TryFrom<crate::KbPairAnalyticSignalEntity> for KbPairAnalyticSignalDto {
|
||||
"cannot parse pair_analytic_signal updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
pair_id: entity.pair_id,
|
||||
signal_kind: entity.signal_kind,
|
||||
@@ -115,6 +115,6 @@ impl TryFrom<crate::KbPairAnalyticSignalEntity> for KbPairAnalyticSignalDto {
|
||||
last_transaction_id: entity.last_transaction_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ impl KbPairCandleDto {
|
||||
last_trade_signature: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
pair_id,
|
||||
timeframe_seconds,
|
||||
@@ -83,7 +83,7 @@ impl KbPairCandleDto {
|
||||
last_trade_signature,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ impl TryFrom<crate::KbPairCandleEntity> for KbPairCandleDto {
|
||||
"cannot parse pair_candle created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -109,9 +109,9 @@ impl TryFrom<crate::KbPairCandleEntity> for KbPairCandleDto {
|
||||
"cannot parse pair_candle updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
pair_id: entity.pair_id,
|
||||
timeframe_seconds: entity.timeframe_seconds,
|
||||
@@ -130,6 +130,6 @@ impl TryFrom<crate::KbPairCandleEntity> for KbPairCandleDto {
|
||||
last_trade_signature: entity.last_trade_signature,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl KbPairMetricDto {
|
||||
/// Creates a new pair-metric DTO.
|
||||
pub fn new(pair_id: i64) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
pair_id,
|
||||
first_slot: None,
|
||||
@@ -54,7 +54,7 @@ impl KbPairMetricDto {
|
||||
last_price_quote_per_base: None,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl TryFrom<crate::KbPairMetricEntity> for KbPairMetricDto {
|
||||
"cannot parse pair_metric created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -80,9 +80,9 @@ impl TryFrom<crate::KbPairMetricEntity> for KbPairMetricDto {
|
||||
"cannot parse pair_metric updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
pair_id: entity.pair_id,
|
||||
first_slot: entity.first_slot,
|
||||
@@ -97,6 +97,6 @@ impl TryFrom<crate::KbPairMetricEntity> for KbPairMetricDto {
|
||||
last_price_quote_per_base: entity.last_price_quote_per_base,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ impl KbPoolDto {
|
||||
status: crate::KbPoolStatus,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
address,
|
||||
@@ -38,7 +38,7 @@ impl KbPoolDto {
|
||||
status,
|
||||
first_seen_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ impl TryFrom<crate::KbPoolEntity> for KbPoolDto {
|
||||
"cannot parse pool first_seen_at '{}': {}",
|
||||
entity.first_seen_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -74,9 +74,9 @@ impl TryFrom<crate::KbPoolEntity> for KbPoolDto {
|
||||
"cannot parse pool updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
address: entity.address,
|
||||
@@ -84,6 +84,6 @@ impl TryFrom<crate::KbPoolEntity> for KbPoolDto {
|
||||
status,
|
||||
first_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ impl KbPoolListingDto {
|
||||
initial_price_quote: std::option::Option<f64>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -54,7 +54,7 @@ impl KbPoolListingDto {
|
||||
initial_quote_reserve,
|
||||
initial_price_quote,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ impl TryFrom<crate::KbPoolListingEntity> for KbPoolListingDto {
|
||||
"cannot parse pool_listing detected_at '{}': {}",
|
||||
entity.detected_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -85,9 +85,9 @@ impl TryFrom<crate::KbPoolListingEntity> for KbPoolListingDto {
|
||||
"cannot parse pool_listing updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -99,6 +99,6 @@ impl TryFrom<crate::KbPoolListingEntity> for KbPoolListingDto {
|
||||
initial_quote_reserve: entity.initial_quote_reserve,
|
||||
initial_price_quote: entity.initial_price_quote,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl KbPoolOriginDto {
|
||||
launch_attribution_id: std::option::Option<i64>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -70,7 +70,7 @@ impl KbPoolOriginDto {
|
||||
launch_attribution_id,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ impl TryFrom<crate::KbPoolOriginEntity> for KbPoolOriginDto {
|
||||
"cannot parse pool_origin created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -101,9 +101,9 @@ impl TryFrom<crate::KbPoolOriginEntity> for KbPoolOriginDto {
|
||||
"cannot parse pool_origin updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -119,6 +119,6 @@ impl TryFrom<crate::KbPoolOriginEntity> for KbPoolOriginDto {
|
||||
launch_attribution_id: entity.launch_attribution_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl KbPoolTokenDto {
|
||||
token_order: std::option::Option<i64>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
pool_id,
|
||||
token_id,
|
||||
@@ -42,7 +42,7 @@ impl KbPoolTokenDto {
|
||||
token_order,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ impl TryFrom<crate::KbPoolTokenEntity> for KbPoolTokenDto {
|
||||
"cannot parse pool_token created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -73,9 +73,9 @@ impl TryFrom<crate::KbPoolTokenEntity> for KbPoolTokenDto {
|
||||
"cannot parse pool_token updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
pool_id: entity.pool_id,
|
||||
token_id: entity.token_id,
|
||||
@@ -84,6 +84,6 @@ impl TryFrom<crate::KbPoolTokenEntity> for KbPoolTokenDto {
|
||||
token_order: entity.token_order,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl KbSwapDto {
|
||||
price_quote: std::option::Option<std::string::String>,
|
||||
trade_side: crate::KbSwapTradeSide,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -70,7 +70,7 @@ impl KbSwapDto {
|
||||
price_quote,
|
||||
trade_side,
|
||||
executed_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ impl TryFrom<crate::KbSwapEntity> for KbSwapDto {
|
||||
"cannot parse swap executed_at '{}': {}",
|
||||
entity.executed_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let slot = match entity.slot {
|
||||
Some(slot) => {
|
||||
@@ -103,12 +103,12 @@ impl TryFrom<crate::KbSwapEntity> for KbSwapDto {
|
||||
"cannot convert swap slot '{}' to u64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -124,6 +124,6 @@ impl TryFrom<crate::KbSwapEntity> for KbSwapDto {
|
||||
price_quote: entity.price_quote,
|
||||
trade_side,
|
||||
executed_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ impl KbTokenDto {
|
||||
is_quote_token: bool,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
mint,
|
||||
symbol,
|
||||
@@ -46,7 +46,7 @@ impl KbTokenDto {
|
||||
is_quote_token,
|
||||
first_seen_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl TryFrom<crate::KbTokenEntity> for KbTokenDto {
|
||||
"cannot parse token first_seen_at '{}': {}",
|
||||
entity.first_seen_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -72,7 +72,7 @@ impl TryFrom<crate::KbTokenEntity> for KbTokenDto {
|
||||
"cannot parse token updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let decimals = match entity.decimals {
|
||||
Some(decimals) => {
|
||||
@@ -84,12 +84,12 @@ impl TryFrom<crate::KbTokenEntity> for KbTokenDto {
|
||||
"cannot convert token decimals '{}' to u8: {}",
|
||||
decimals, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
mint: entity.mint,
|
||||
symbol: entity.symbol,
|
||||
@@ -99,6 +99,6 @@ impl TryFrom<crate::KbTokenEntity> for KbTokenDto {
|
||||
is_quote_token: entity.is_quote_token != 0,
|
||||
first_seen_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl KbTokenBurnEventDto {
|
||||
amount: std::string::String,
|
||||
supply_after: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
token_id,
|
||||
signature,
|
||||
@@ -50,24 +50,21 @@ impl KbTokenBurnEventDto {
|
||||
amount,
|
||||
supply_after,
|
||||
executed_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<crate::KbTokenBurnEventEntity> for KbTokenBurnEventDto {
|
||||
type Error = crate::KbError;
|
||||
|
||||
fn try_from(
|
||||
entity: crate::KbTokenBurnEventEntity,
|
||||
) -> Result<Self, Self::Error> {
|
||||
fn try_from(entity: crate::KbTokenBurnEventEntity) -> Result<Self, Self::Error> {
|
||||
let executed_at_result = chrono::DateTime::parse_from_rfc3339(&entity.executed_at);
|
||||
let executed_at = match executed_at_result {
|
||||
Ok(executed_at) => executed_at.with_timezone(&chrono::Utc),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot parse token burn event executed_at '{}': {}",
|
||||
entity.executed_at,
|
||||
error
|
||||
entity.executed_at, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
@@ -79,15 +76,14 @@ impl TryFrom<crate::KbTokenBurnEventEntity> for KbTokenBurnEventDto {
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot convert token burn event slot '{}' to u64: {}",
|
||||
slot,
|
||||
error
|
||||
slot, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
token_id: entity.token_id,
|
||||
signature: entity.signature,
|
||||
@@ -98,6 +94,6 @@ impl TryFrom<crate::KbTokenBurnEventEntity> for KbTokenBurnEventDto {
|
||||
amount: entity.amount,
|
||||
supply_after: entity.supply_after,
|
||||
executed_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl KbTokenMintEventDto {
|
||||
amount: std::string::String,
|
||||
supply_after: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
token_id,
|
||||
signature,
|
||||
@@ -50,7 +50,7 @@ impl KbTokenMintEventDto {
|
||||
amount,
|
||||
supply_after,
|
||||
executed_at: chrono::Utc::now(),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl TryFrom<crate::KbTokenMintEventEntity> for KbTokenMintEventDto {
|
||||
"cannot parse token mint event executed_at '{}': {}",
|
||||
entity.executed_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let slot = match entity.slot {
|
||||
Some(slot) => {
|
||||
@@ -78,12 +78,12 @@ impl TryFrom<crate::KbTokenMintEventEntity> for KbTokenMintEventDto {
|
||||
"cannot convert token mint event slot '{}' to u64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
token_id: entity.token_id,
|
||||
signature: entity.signature,
|
||||
@@ -94,6 +94,6 @@ impl TryFrom<crate::KbTokenMintEventEntity> for KbTokenMintEventDto {
|
||||
amount: entity.amount,
|
||||
supply_after: entity.supply_after,
|
||||
executed_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl KbTradeEventDto {
|
||||
payload_json: std::string::String,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
dex_id,
|
||||
pool_id,
|
||||
@@ -86,7 +86,7 @@ impl KbTradeEventDto {
|
||||
payload_json,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ impl TryFrom<crate::KbTradeEventEntity> for KbTradeEventDto {
|
||||
"cannot parse trade_event created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -118,9 +118,9 @@ impl TryFrom<crate::KbTradeEventEntity> for KbTradeEventDto {
|
||||
"cannot parse trade_event updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
dex_id: entity.dex_id,
|
||||
pool_id: entity.pool_id,
|
||||
@@ -140,14 +140,14 @@ impl TryFrom<crate::KbTradeEventEntity> for KbTradeEventDto {
|
||||
payload_json: entity.payload_json,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_trade_side_from_string(value: &str) -> crate::KbSwapTradeSide {
|
||||
match value {
|
||||
"BuyBase" => crate::KbSwapTradeSide::BuyBase,
|
||||
"SellBase" => crate::KbSwapTradeSide::SellBase,
|
||||
_ => crate::KbSwapTradeSide::Unknown,
|
||||
"BuyBase" => return crate::KbSwapTradeSide::BuyBase,
|
||||
"SellBase" => return crate::KbSwapTradeSide::SellBase,
|
||||
_ => return crate::KbSwapTradeSide::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ impl KbWalletDto {
|
||||
label: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
address,
|
||||
label,
|
||||
first_seen_at: now,
|
||||
last_seen_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ impl TryFrom<crate::KbWalletEntity> for KbWalletDto {
|
||||
"cannot parse wallet first_seen_at '{}': {}",
|
||||
entity.first_seen_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let last_seen_at_result = chrono::DateTime::parse_from_rfc3339(&entity.last_seen_at);
|
||||
let last_seen_at = match last_seen_at_result {
|
||||
@@ -56,14 +56,14 @@ impl TryFrom<crate::KbWalletEntity> for KbWalletDto {
|
||||
"cannot parse wallet last_seen_at '{}': {}",
|
||||
entity.last_seen_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
address: entity.address,
|
||||
label: entity.label,
|
||||
first_seen_at,
|
||||
last_seen_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl KbWalletHoldingDto {
|
||||
source_endpoint_name: std::option::Option<std::string::String>,
|
||||
) -> Self {
|
||||
let now = chrono::Utc::now();
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
wallet_id,
|
||||
token_id,
|
||||
@@ -70,7 +70,7 @@ impl KbWalletHoldingDto {
|
||||
source_endpoint_name,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ impl TryFrom<crate::KbWalletHoldingEntity> for KbWalletHoldingDto {
|
||||
"cannot parse wallet_holding created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -101,9 +101,9 @@ impl TryFrom<crate::KbWalletHoldingEntity> for KbWalletHoldingDto {
|
||||
"cannot parse wallet_holding updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
wallet_id: entity.wallet_id,
|
||||
token_id: entity.token_id,
|
||||
|
||||
@@ -52,8 +52,7 @@ impl KbWalletParticipationDto {
|
||||
pair_id,
|
||||
role.as_str(),
|
||||
);
|
||||
|
||||
Self {
|
||||
return Self {
|
||||
id: None,
|
||||
wallet_id,
|
||||
transaction_id,
|
||||
@@ -66,7 +65,7 @@ impl KbWalletParticipationDto {
|
||||
source_endpoint_name,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ impl TryFrom<crate::KbWalletParticipationEntity> for KbWalletParticipationDto {
|
||||
"cannot parse wallet_participation created_at '{}': {}",
|
||||
entity.created_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
|
||||
let updated_at = match updated_at_result {
|
||||
@@ -97,9 +96,9 @@ impl TryFrom<crate::KbWalletParticipationEntity> for KbWalletParticipationDto {
|
||||
"cannot parse wallet_participation updated_at '{}': {}",
|
||||
entity.updated_at, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(Self {
|
||||
return Ok(Self {
|
||||
id: Some(entity.id),
|
||||
wallet_id: entity.wallet_id,
|
||||
transaction_id: entity.transaction_id,
|
||||
@@ -112,7 +111,7 @@ impl TryFrom<crate::KbWalletParticipationEntity> for KbWalletParticipationDto {
|
||||
source_endpoint_name: entity.source_endpoint_name,
|
||||
created_at,
|
||||
updated_at,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,8 +126,8 @@ fn kb_build_wallet_participation_unique_key(
|
||||
let decoded_event_id_value = decoded_event_id.unwrap_or_default();
|
||||
let pool_id_value = pool_id.unwrap_or_default();
|
||||
let pair_id_value = pair_id.unwrap_or_default();
|
||||
format!(
|
||||
return format!(
|
||||
"{}:{}:{}:{}:{}:{}",
|
||||
wallet_id, transaction_id, decoded_event_id_value, pool_id_value, pair_id_value, role
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ pub use chain_slot::get_chain_slot;
|
||||
pub use chain_slot::list_recent_chain_slots;
|
||||
pub use chain_slot::upsert_chain_slot;
|
||||
pub use chain_transaction::get_chain_transaction_by_signature;
|
||||
pub use chain_transaction::list_chain_transaction_signatures_for_replay;
|
||||
pub use chain_transaction::list_recent_chain_transactions;
|
||||
pub use chain_transaction::upsert_chain_transaction;
|
||||
pub use db_metadata::get_db_metadata;
|
||||
@@ -59,6 +60,7 @@ pub use dex::get_dex_by_code;
|
||||
pub use dex::list_dexes;
|
||||
pub use dex::upsert_dex;
|
||||
pub use dex_decoded_event::get_dex_decoded_event_by_key;
|
||||
pub use dex_decoded_event::get_latest_pump_fun_create_payload_by_mint;
|
||||
pub use dex_decoded_event::list_dex_decoded_events_by_transaction_id;
|
||||
pub use dex_decoded_event::upsert_dex_decoded_event;
|
||||
pub use known_http_endpoint::get_known_http_endpoint;
|
||||
@@ -85,6 +87,7 @@ pub use onchain_observation::insert_onchain_observation;
|
||||
pub use onchain_observation::list_recent_onchain_observations;
|
||||
pub use pair::get_pair_by_pool_id;
|
||||
pub use pair::list_pairs;
|
||||
pub use pair::update_pair_symbol;
|
||||
pub use pair::upsert_pair;
|
||||
pub use pair_analytic_signal::get_pair_analytic_signal_by_key;
|
||||
pub use pair_analytic_signal::list_pair_analytic_signals_by_pair_id;
|
||||
@@ -108,8 +111,10 @@ pub use pool_token::list_pool_tokens_by_pool_id;
|
||||
pub use pool_token::upsert_pool_token;
|
||||
pub use swap::list_recent_swaps;
|
||||
pub use swap::upsert_swap;
|
||||
pub use token::get_token_by_id;
|
||||
pub use token::get_token_by_mint;
|
||||
pub use token::list_tokens;
|
||||
pub use token::list_tokens_missing_metadata;
|
||||
pub use token::upsert_token;
|
||||
pub use token_burn_event::list_recent_token_burn_events;
|
||||
pub use token_burn_event::upsert_token_burn_event;
|
||||
|
||||
@@ -15,7 +15,7 @@ pub async fn insert_analysis_signal(
|
||||
"cannot serialize analysis signal payload: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
@@ -49,10 +49,10 @@ VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
"cannot insert kb_analysis_signals on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(query_result.last_insert_rowid())
|
||||
}
|
||||
return Ok(query_result.last_insert_rowid());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ LIMIT ?
|
||||
"cannot list analysis signals on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -103,8 +103,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,10 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
"cannot insert kb_chain_instructions on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(insert_result.last_insert_rowid())
|
||||
}
|
||||
return Ok(insert_result.last_insert_rowid());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ ORDER BY instruction_index ASC, inner_instruction_index ASC, id ASC
|
||||
"cannot list kb_chain_instructions for transaction_id '{}' on sqlite: {}",
|
||||
transaction_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -114,8 +114,8 @@ ORDER BY instruction_index ASC, inner_instruction_index ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +141,8 @@ WHERE transaction_id = ?
|
||||
transaction_id, error
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,9 +163,9 @@ mod tests {
|
||||
use_wal: true,
|
||||
},
|
||||
};
|
||||
crate::KbDatabase::connect_and_initialize(&config)
|
||||
return crate::KbDatabase::connect_and_initialize(&config)
|
||||
.await
|
||||
.expect("database init must succeed")
|
||||
.expect("database init must succeed");
|
||||
}
|
||||
|
||||
async fn make_transaction(database: &crate::KbDatabase) -> i64 {
|
||||
@@ -179,9 +179,9 @@ mod tests {
|
||||
None,
|
||||
r#"{"transaction":{"message":{"instructions":[]}}}"#.to_string(),
|
||||
);
|
||||
crate::upsert_chain_transaction(database, &dto)
|
||||
return crate::upsert_chain_transaction(database, &dto)
|
||||
.await
|
||||
.expect("chain transaction upsert must succeed")
|
||||
.expect("chain transaction upsert must succeed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -15,7 +15,7 @@ pub async fn upsert_chain_slot(
|
||||
"cannot convert chain slot '{}' to i64: {}",
|
||||
dto.slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let parent_slot = match dto.parent_slot {
|
||||
Some(parent_slot) => {
|
||||
@@ -27,9 +27,9 @@ pub async fn upsert_chain_slot(
|
||||
"cannot convert chain parent_slot '{}' to i64: {}",
|
||||
parent_slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -63,8 +63,8 @@ ON CONFLICT(slot) DO UPDATE SET
|
||||
error
|
||||
)));
|
||||
}
|
||||
Ok(dto.slot)
|
||||
}
|
||||
return Ok(dto.slot);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ pub async fn get_chain_slot(
|
||||
"cannot convert requested chain slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
@@ -108,19 +108,19 @@ LIMIT 1
|
||||
"cannot fetch kb_chain_slots for slot '{}' on sqlite: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbChainSlotDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ LIMIT ?
|
||||
"cannot list kb_chain_slots on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -168,8 +168,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,9 +190,9 @@ mod tests {
|
||||
use_wal: true,
|
||||
},
|
||||
};
|
||||
crate::KbDatabase::connect_and_initialize(&config)
|
||||
return crate::KbDatabase::connect_and_initialize(&config)
|
||||
.await
|
||||
.expect("database init must succeed")
|
||||
.expect("database init must succeed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -17,9 +17,9 @@ pub async fn upsert_chain_transaction(
|
||||
"cannot convert chain transaction slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -80,13 +80,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_chain_transactions id for signature '{}' on sqlite: {}",
|
||||
dto.signature, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_chain_transactions id for signature '{}' on sqlite: {}",
|
||||
dto.signature, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,19 +128,19 @@ LIMIT 1
|
||||
"cannot fetch kb_chain_transactions for signature '{}' on sqlite: {}",
|
||||
signature, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbChainTransactionDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +183,7 @@ LIMIT ?
|
||||
"cannot list kb_chain_transactions on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -192,8 +194,49 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists persisted chain transaction signatures for local pipeline replay.
|
||||
pub async fn list_chain_transaction_signatures_for_replay(
|
||||
database: &crate::KbDatabase,
|
||||
limit: std::option::Option<i64>,
|
||||
) -> Result<std::vec::Vec<std::string::String>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let effective_limit = match limit {
|
||||
Some(limit) => {
|
||||
if limit <= 0 {
|
||||
10_000
|
||||
} else {
|
||||
limit
|
||||
}
|
||||
},
|
||||
None => 10_000,
|
||||
};
|
||||
let query_result = sqlx::query_scalar::<sqlx::Sqlite, std::string::String>(
|
||||
r#"
|
||||
SELECT signature
|
||||
FROM kb_chain_transactions
|
||||
ORDER BY id ASC
|
||||
LIMIT ?
|
||||
"#,
|
||||
)
|
||||
.bind(effective_limit)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(signatures) => return Ok(signatures),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot list kb_chain_transactions signatures for local replay on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,9 +257,9 @@ mod tests {
|
||||
use_wal: true,
|
||||
},
|
||||
};
|
||||
crate::KbDatabase::connect_and_initialize(&config)
|
||||
return crate::KbDatabase::connect_and_initialize(&config)
|
||||
.await
|
||||
.expect("database init must succeed")
|
||||
.expect("database init must succeed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -249,10 +292,7 @@ mod tests {
|
||||
assert_eq!(fetched.signature, "sig-chain-transaction-1");
|
||||
assert_eq!(fetched.slot, Some(515151));
|
||||
assert_eq!(fetched.block_time_unix, Some(1_700_000_001));
|
||||
assert_eq!(
|
||||
fetched.source_endpoint_name,
|
||||
Some("helius_primary_http".to_string())
|
||||
);
|
||||
assert_eq!(fetched.source_endpoint_name, Some("helius_primary_http".to_string()));
|
||||
assert_eq!(fetched.version_text, Some("0".to_string()));
|
||||
assert_eq!(fetched.meta_json, Some(r#"{"fee":5000}"#.to_string()));
|
||||
let listed = crate::list_recent_chain_transactions(&database, 10)
|
||||
|
||||
@@ -29,13 +29,15 @@ ON CONFLICT(key) DO UPDATE SET
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_db_metadata on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_db_metadata on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,19 +69,19 @@ LIMIT 1
|
||||
"cannot read kb_db_metadata '{}' on sqlite: {}",
|
||||
key, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbDbMetadataDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +110,7 @@ ORDER BY key ASC
|
||||
"cannot list kb_db_metadata on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -119,8 +121,8 @@ ORDER BY key ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,9 +148,7 @@ mod tests {
|
||||
.await
|
||||
.expect("database init must succeed");
|
||||
let dto = crate::KbDbMetadataDto::new("schema_version".to_string(), "0.5.0".to_string());
|
||||
crate::upsert_db_metadata(&database, &dto)
|
||||
.await
|
||||
.expect("upsert must succeed");
|
||||
crate::upsert_db_metadata(&database, &dto).await.expect("upsert must succeed");
|
||||
let fetched = crate::get_db_metadata(&database, "schema_version")
|
||||
.await
|
||||
.expect("fetch must succeed");
|
||||
@@ -156,9 +156,7 @@ mod tests {
|
||||
let fetched = fetched.expect("metadata must exist");
|
||||
assert_eq!(fetched.key, "schema_version");
|
||||
assert_eq!(fetched.value, "0.5.0");
|
||||
let listed = crate::list_db_metadata(&database)
|
||||
.await
|
||||
.expect("list must succeed");
|
||||
let listed = crate::list_db_metadata(&database).await.expect("list must succeed");
|
||||
assert!(!listed.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ VALUES (?, ?, ?, ?, ?)
|
||||
"cannot insert kb_db_runtime_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(query_result.last_insert_rowid())
|
||||
}
|
||||
return Ok(query_result.last_insert_rowid());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ LIMIT ?
|
||||
"cannot list runtime events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -87,8 +87,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,13 +56,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_dexes id for code '{}' on sqlite: {}",
|
||||
dto.code, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_dexes id for code '{}' on sqlite: {}",
|
||||
dto.code, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,19 +101,19 @@ LIMIT 1
|
||||
"cannot read kb_dexes '{}' on sqlite: {}",
|
||||
code, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbDexDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +147,7 @@ ORDER BY code ASC
|
||||
"cannot list kb_dexes on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -156,8 +158,8 @@ ORDER BY code ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,13 +186,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
@@ -200,9 +196,7 @@ mod tests {
|
||||
.expect("get dex must succeed");
|
||||
assert!(dex.is_some());
|
||||
assert_eq!(dex.expect("dex must exist").name, "Raydium");
|
||||
let dexes = crate::list_dexes(&database)
|
||||
.await
|
||||
.expect("list dexes must succeed");
|
||||
let dexes = crate::list_dexes(&database).await.expect("list dexes must succeed");
|
||||
assert_eq!(dexes.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,13 +77,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_dex_decoded_events id on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_dex_decoded_events id on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,19 +137,19 @@ LIMIT 1
|
||||
"cannot fetch kb_dex_decoded_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbDexDecodedEventDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@ ORDER BY id ASC
|
||||
"cannot list kb_dex_decoded_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -200,8 +202,48 @@ ORDER BY id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the latest Pump.fun create payload associated with a token mint.
|
||||
pub async fn get_latest_pump_fun_create_payload_by_mint(
|
||||
database: &crate::KbDatabase,
|
||||
mint: &str,
|
||||
) -> Result<std::option::Option<std::string::String>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let payload_result = sqlx::query_scalar::<sqlx::Sqlite, std::string::String>(
|
||||
r#"
|
||||
SELECT payload_json
|
||||
FROM kb_dex_decoded_events
|
||||
WHERE protocol_name = 'pump_fun'
|
||||
AND event_kind IN ('pump_fun.create', 'pump_fun.create_v2_token')
|
||||
AND (
|
||||
token_a_mint = ?
|
||||
OR json_extract(payload_json, '$.mint') = ?
|
||||
OR json_extract(payload_json, '$.tokenMint') = ?
|
||||
)
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(mint)
|
||||
.bind(mint)
|
||||
.bind(mint)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
match payload_result {
|
||||
Ok(payload_option) => return Ok(payload_option),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot read latest pump.fun create payload for mint '{}' on sqlite: {}",
|
||||
mint, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +270,7 @@ mod tests {
|
||||
};
|
||||
let database_result = crate::KbDatabase::connect_and_initialize(&config).await;
|
||||
match database_result {
|
||||
Ok(database) => database,
|
||||
Ok(database) => return database,
|
||||
Err(error) => panic!("database init must succeed: {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,13 +46,15 @@ ON CONFLICT(name) DO UPDATE SET
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_known_http_endpoints on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_known_http_endpoints on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,19 +90,19 @@ LIMIT 1
|
||||
"cannot read known http endpoint '{}' on sqlite: {}",
|
||||
name, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbKnownHttpEndpointDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +135,7 @@ ORDER BY name ASC
|
||||
"cannot list known http endpoints on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -144,8 +146,8 @@ ORDER BY name ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,9 +189,7 @@ mod tests {
|
||||
let fetched = fetched.expect("endpoint must exist");
|
||||
assert_eq!(fetched.provider, "helius");
|
||||
assert_eq!(fetched.roles.len(), 2);
|
||||
let listed = crate::list_known_http_endpoints(&database)
|
||||
.await
|
||||
.expect("list must succeed");
|
||||
let listed = crate::list_known_http_endpoints(&database).await.expect("list must succeed");
|
||||
assert_eq!(listed.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ pub async fn upsert_known_ws_endpoint(
|
||||
Ok(entity) => entity,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
@@ -46,13 +45,15 @@ ON CONFLICT(name) DO UPDATE SET
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_known_ws_endpoints on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(_) => return Ok(()),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot upsert kb_known_ws_endpoints on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,19 +89,19 @@ LIMIT 1
|
||||
"cannot read known ws endpoint '{}' on sqlite: {}",
|
||||
name, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbKnownWsEndpointDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +134,7 @@ ORDER BY name ASC
|
||||
"cannot list known ws endpoints on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -144,8 +145,8 @@ ORDER BY name ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,9 +188,7 @@ mod tests {
|
||||
let fetched = fetched.expect("endpoint must exist");
|
||||
assert_eq!(fetched.provider, "solana");
|
||||
assert_eq!(fetched.roles.len(), 2);
|
||||
let listed = crate::list_known_ws_endpoints(&database)
|
||||
.await
|
||||
.expect("list must succeed");
|
||||
let listed = crate::list_known_ws_endpoints(&database).await.expect("list must succeed");
|
||||
assert_eq!(listed.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,13 +68,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_attributions id for decoded_event_id '{}' on sqlite: {}",
|
||||
dto.decoded_event_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_attributions id for decoded_event_id '{}' on sqlite: {}",
|
||||
dto.decoded_event_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +87,8 @@ pub async fn get_launch_attribution_by_decoded_event_id(
|
||||
) -> Result<std::option::Option<crate::KbLaunchAttributionDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchAttributionEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchAttributionEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
launch_surface_id,
|
||||
@@ -105,10 +106,10 @@ FROM kb_launch_attributions
|
||||
WHERE decoded_event_id = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(decoded_event_id)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(decoded_event_id)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
let entity_option = match query_result {
|
||||
Ok(entity_option) => entity_option,
|
||||
Err(error) => {
|
||||
@@ -116,13 +117,13 @@ LIMIT 1
|
||||
"cannot read kb_launch_attributions by decoded_event_id '{}' on sqlite: {}",
|
||||
decoded_event_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbLaunchAttributionDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbLaunchAttributionDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,9 +134,8 @@ pub async fn list_launch_attributions_by_pool_id(
|
||||
) -> Result<std::vec::Vec<crate::KbLaunchAttributionDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchAttributionEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchAttributionEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
launch_surface_id,
|
||||
@@ -153,10 +153,10 @@ FROM kb_launch_attributions
|
||||
WHERE pool_id = ?
|
||||
ORDER BY attributed_at ASC, id ASC
|
||||
"#,
|
||||
)
|
||||
.bind(pool_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(pool_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
@@ -164,7 +164,7 @@ ORDER BY attributed_at ASC, id ASC
|
||||
"cannot list kb_launch_attributions by pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -175,7 +175,7 @@ ORDER BY attributed_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_surfaces id for code '{}' on sqlite: {}",
|
||||
dto.code, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_surfaces id for code '{}' on sqlite: {}",
|
||||
dto.code, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +72,8 @@ pub async fn get_launch_surface_by_code(
|
||||
) -> Result<std::option::Option<crate::KbLaunchSurfaceDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
code,
|
||||
@@ -85,10 +86,10 @@ FROM kb_launch_surfaces
|
||||
WHERE code = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(code)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(code)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
let entity_option = match query_result {
|
||||
Ok(entity_option) => entity_option,
|
||||
Err(error) => {
|
||||
@@ -96,13 +97,13 @@ LIMIT 1
|
||||
"cannot read kb_launch_surfaces '{}' on sqlite: {}",
|
||||
code, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbLaunchSurfaceDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbLaunchSurfaceDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +113,8 @@ pub async fn list_launch_surfaces(
|
||||
) -> Result<std::vec::Vec<crate::KbLaunchSurfaceDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
code,
|
||||
@@ -126,9 +126,9 @@ SELECT
|
||||
FROM kb_launch_surfaces
|
||||
ORDER BY code ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
@@ -136,7 +136,7 @@ ORDER BY code ASC
|
||||
"cannot list kb_launch_surfaces on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -147,7 +147,7 @@ ORDER BY code ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,13 +50,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_surface_keys id for '{}:{}' on sqlite: {}",
|
||||
dto.match_kind, dto.match_value, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_launch_surface_keys id for '{}:{}' on sqlite: {}",
|
||||
dto.match_kind, dto.match_value, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +70,8 @@ pub async fn get_launch_surface_key_by_match(
|
||||
) -> Result<std::option::Option<crate::KbLaunchSurfaceKeyDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceKeyEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceKeyEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
launch_surface_id,
|
||||
@@ -82,11 +83,11 @@ FROM kb_launch_surface_keys
|
||||
WHERE match_kind = ? AND match_value = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(match_kind)
|
||||
.bind(match_value)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(match_kind)
|
||||
.bind(match_value)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
let entity_option = match query_result {
|
||||
Ok(entity_option) => entity_option,
|
||||
Err(error) => {
|
||||
@@ -94,13 +95,13 @@ LIMIT 1
|
||||
"cannot read kb_launch_surface_keys '{}:{}' on sqlite: {}",
|
||||
match_kind, match_value, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbLaunchSurfaceKeyDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbLaunchSurfaceKeyDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +112,8 @@ pub async fn list_launch_surface_keys_by_surface_id(
|
||||
) -> Result<std::vec::Vec<crate::KbLaunchSurfaceKeyDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceKeyEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbLaunchSurfaceKeyEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
launch_surface_id,
|
||||
@@ -125,10 +125,10 @@ FROM kb_launch_surface_keys
|
||||
WHERE launch_surface_id = ?
|
||||
ORDER BY match_kind ASC, match_value ASC
|
||||
"#,
|
||||
)
|
||||
.bind(launch_surface_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(launch_surface_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
@@ -136,7 +136,7 @@ ORDER BY match_kind ASC, match_value ASC
|
||||
"cannot list kb_launch_surface_keys by surface_id '{}' on sqlite: {}",
|
||||
launch_surface_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -147,7 +147,7 @@ ORDER BY match_kind ASC, match_value ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ pub async fn upsert_liquidity_event(
|
||||
"cannot convert liquidity event slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -96,13 +96,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_liquidity_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_liquidity_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ LIMIT ?
|
||||
"cannot list kb_liquidity_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -161,7 +163,7 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,13 +63,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match select_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_observed_tokens id for mint '{}' on sqlite: {}",
|
||||
dto.mint, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_observed_tokens id for mint '{}' on sqlite: {}",
|
||||
dto.mint, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,19 +110,19 @@ LIMIT 1
|
||||
"cannot read observed token '{}' on sqlite: {}",
|
||||
mint, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbObservedTokenDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +164,7 @@ LIMIT ?
|
||||
"cannot list observed tokens on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -173,8 +175,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,9 +224,7 @@ mod tests {
|
||||
assert_eq!(fetched.symbol.as_deref(), Some("WSOL"));
|
||||
assert_eq!(fetched.decimals, Some(9));
|
||||
assert_eq!(fetched.status, crate::KbObservedTokenStatus::Active);
|
||||
let listed = crate::list_observed_tokens(&database, 10)
|
||||
.await
|
||||
.expect("list must succeed");
|
||||
let listed = crate::list_observed_tokens(&database, 10).await.expect("list must succeed");
|
||||
assert_eq!(listed.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub async fn insert_onchain_observation(
|
||||
"cannot serialize on-chain observation payload: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let slot_i64 = match dto.slot {
|
||||
Some(slot) => {
|
||||
@@ -27,9 +27,9 @@ pub async fn insert_onchain_observation(
|
||||
"cannot convert on-chain observation slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -64,10 +64,10 @@ VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
"cannot insert kb_onchain_observations on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
Ok(query_result.last_insert_rowid())
|
||||
}
|
||||
return Ok(query_result.last_insert_rowid());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ LIMIT ?
|
||||
"cannot list on-chain observations on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -118,8 +118,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ ON CONFLICT(pool_id) DO UPDATE SET
|
||||
dex_id = excluded.dex_id,
|
||||
base_token_id = excluded.base_token_id,
|
||||
quote_token_id = excluded.quote_token_id,
|
||||
symbol = excluded.symbol,
|
||||
symbol = CASE
|
||||
WHEN excluded.symbol IS NOT NULL AND trim(excluded.symbol) <> ''
|
||||
THEN excluded.symbol
|
||||
ELSE kb_pairs.symbol
|
||||
END,
|
||||
updated_at = excluded.updated_at
|
||||
"#,
|
||||
)
|
||||
@@ -56,13 +60,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pairs id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pairs id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,19 +105,54 @@ LIMIT 1
|
||||
"cannot read kb_pairs by pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbPairDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the display symbol of one normalized pair row.
|
||||
pub async fn update_pair_symbol(
|
||||
database: &crate::KbDatabase,
|
||||
pair_id: i64,
|
||||
symbol: std::option::Option<&str>,
|
||||
) -> Result<bool, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
r#"
|
||||
UPDATE kb_pairs
|
||||
SET
|
||||
symbol = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
"#,
|
||||
)
|
||||
.bind(symbol)
|
||||
.bind(chrono::Utc::now().to_rfc3339())
|
||||
.bind(pair_id)
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(done) => return Ok(done.rows_affected() > 0),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot update kb_pairs symbol for id '{}' on sqlite: {}",
|
||||
pair_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +186,7 @@ ORDER BY id ASC
|
||||
"cannot list kb_pairs on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -156,8 +197,8 @@ ORDER BY id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,13 +225,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
@@ -248,13 +283,8 @@ mod tests {
|
||||
.await
|
||||
.expect("get pair must succeed");
|
||||
assert!(pair.is_some());
|
||||
assert_eq!(
|
||||
pair.expect("pair must exist").symbol.as_deref(),
|
||||
Some("BASE/WSOL")
|
||||
);
|
||||
let pairs = crate::list_pairs(&database)
|
||||
.await
|
||||
.expect("list pairs must succeed");
|
||||
assert_eq!(pair.expect("pair must exist").symbol.as_deref(), Some("BASE/WSOL"));
|
||||
let pairs = crate::list_pairs(&database).await.expect("list pairs must succeed");
|
||||
assert_eq!(pairs.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub async fn upsert_pair_analytic_signal(
|
||||
"cannot serialize pair analytic signal payload: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
@@ -77,13 +77,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_analytic_signals id on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_analytic_signals id on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,9 +99,8 @@ pub async fn get_pair_analytic_signal_by_key(
|
||||
) -> Result<std::option::Option<crate::KbPairAnalyticSignalDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbPairAnalyticSignalEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbPairAnalyticSignalEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
pair_id,
|
||||
@@ -117,13 +118,13 @@ FROM kb_pair_analytic_signals
|
||||
WHERE pair_id = ? AND signal_kind = ? AND timeframe_seconds = ? AND bucket_start_unix = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(pair_id)
|
||||
.bind(signal_kind)
|
||||
.bind(timeframe_seconds)
|
||||
.bind(bucket_start_unix)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(pair_id)
|
||||
.bind(signal_kind)
|
||||
.bind(timeframe_seconds)
|
||||
.bind(bucket_start_unix)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
let entity_option = match query_result {
|
||||
Ok(entity_option) => entity_option,
|
||||
Err(error) => {
|
||||
@@ -131,13 +132,13 @@ LIMIT 1
|
||||
"cannot read kb_pair_analytic_signals by key on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbPairAnalyticSignalDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbPairAnalyticSignalDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +149,8 @@ pub async fn list_pair_analytic_signals_by_pair_id(
|
||||
) -> Result<std::vec::Vec<crate::KbPairAnalyticSignalDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbPairAnalyticSignalEntity>(
|
||||
r#"
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbPairAnalyticSignalEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
pair_id,
|
||||
@@ -168,10 +168,10 @@ FROM kb_pair_analytic_signals
|
||||
WHERE pair_id = ?
|
||||
ORDER BY timeframe_seconds ASC, bucket_start_unix ASC, signal_kind ASC, id ASC
|
||||
"#,
|
||||
)
|
||||
.bind(pair_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
)
|
||||
.bind(pair_id)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
@@ -179,7 +179,7 @@ ORDER BY timeframe_seconds ASC, bucket_start_unix ASC, signal_kind ASC, id ASC
|
||||
"cannot list kb_pair_analytic_signals by pair_id '{}' on sqlite: {}",
|
||||
pair_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -190,7 +190,7 @@ ORDER BY timeframe_seconds ASC, bucket_start_unix ASC, signal_kind ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +87,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_candles id for pair_id '{}' timeframe '{}' bucket '{}' on sqlite: {}",
|
||||
dto.pair_id, dto.timeframe_seconds, dto.bucket_start_unix, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_candles id for pair_id '{}' timeframe '{}' bucket '{}' on sqlite: {}",
|
||||
dto.pair_id, dto.timeframe_seconds, dto.bucket_start_unix, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,13 +146,13 @@ LIMIT 1
|
||||
"cannot read kb_pair_candles by key on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbPairCandleDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbPairCandleDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +201,7 @@ ORDER BY bucket_start_unix ASC, id ASC
|
||||
"cannot list kb_pair_candles by pair_id '{}' timeframe '{}' on sqlite: {}",
|
||||
pair_id, timeframe_seconds, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -210,7 +212,7 @@ ORDER BY bucket_start_unix ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,13 +74,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_metrics id for pair_id '{}' on sqlite: {}",
|
||||
dto.pair_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pair_metrics id for pair_id '{}' on sqlite: {}",
|
||||
dto.pair_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +125,13 @@ LIMIT 1
|
||||
"cannot read kb_pair_metrics by pair_id '{}' on sqlite: {}",
|
||||
pair_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbPairMetricDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbPairMetricDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +171,7 @@ ORDER BY pair_id ASC
|
||||
"cannot list kb_pair_metrics on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -180,7 +182,7 @@ ORDER BY pair_id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pools id for address '{}' on sqlite: {}",
|
||||
dto.address, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pools id for address '{}' on sqlite: {}",
|
||||
dto.address, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,19 +97,19 @@ LIMIT 1
|
||||
"cannot read kb_pools '{}' on sqlite: {}",
|
||||
address, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbPoolDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +142,7 @@ ORDER BY id ASC
|
||||
"cannot list kb_pools on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -151,8 +153,8 @@ ORDER BY id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +181,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
@@ -206,13 +202,8 @@ mod tests {
|
||||
.await
|
||||
.expect("get pool must succeed");
|
||||
assert!(pool.is_some());
|
||||
assert_eq!(
|
||||
pool.expect("pool must exist").pool_kind,
|
||||
crate::KbPoolKind::Amm
|
||||
);
|
||||
let pools = crate::list_pools(&database)
|
||||
.await
|
||||
.expect("list pools must succeed");
|
||||
assert_eq!(pool.expect("pool must exist").pool_kind, crate::KbPoolKind::Amm);
|
||||
let pools = crate::list_pools(&database).await.expect("list pools must succeed");
|
||||
assert_eq!(pools.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,13 +66,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_listings id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_listings id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,19 +114,19 @@ LIMIT 1
|
||||
"cannot read kb_pool_listings by pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbPoolListingDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +163,7 @@ ORDER BY detected_at ASC, id ASC
|
||||
"cannot list kb_pool_listings on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -172,8 +174,8 @@ ORDER BY detected_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,13 +202,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
|
||||
@@ -69,13 +69,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_origins id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_origins id for pool_id '{}' on sqlite: {}",
|
||||
dto.pool_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,13 +121,13 @@ LIMIT 1
|
||||
"cannot read kb_pool_origins by pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbPoolOriginDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbPoolOriginDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +168,7 @@ ORDER BY created_at ASC, id ASC
|
||||
"cannot list kb_pool_origins on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -177,7 +179,7 @@ ORDER BY created_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +56,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_tokens id on sqlite: {}",
|
||||
error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_pool_tokens id on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +101,7 @@ ORDER BY token_order ASC, id ASC
|
||||
"cannot list kb_pool_tokens for pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -110,8 +112,8 @@ ORDER BY token_order ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,13 +140,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
|
||||
@@ -17,9 +17,9 @@ pub async fn upsert_swap(
|
||||
"cannot convert swap slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -93,13 +93,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_swaps id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_swaps id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +148,7 @@ LIMIT ?
|
||||
"cannot list kb_swaps on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -157,7 +159,7 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +60,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_tokens id for mint '{}' on sqlite: {}",
|
||||
dto.mint, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_tokens id for mint '{}' on sqlite: {}",
|
||||
dto.mint, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,22 +106,71 @@ LIMIT 1
|
||||
"cannot read kb_tokens '{}' on sqlite: {}",
|
||||
mint, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbTokenDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => Ok(Some(dto)),
|
||||
Err(error) => Err(error),
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads one normalized token row by internal id.
|
||||
pub async fn get_token_by_id(
|
||||
database: &crate::KbDatabase,
|
||||
token_id: i64,
|
||||
) -> Result<std::option::Option<crate::KbTokenDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::KbTokenEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
mint,
|
||||
symbol,
|
||||
name,
|
||||
decimals,
|
||||
token_program,
|
||||
is_quote_token,
|
||||
first_seen_at,
|
||||
updated_at
|
||||
FROM kb_tokens
|
||||
WHERE id = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(token_id)
|
||||
.fetch_optional(pool)
|
||||
.await;
|
||||
let entity_option = match query_result {
|
||||
Ok(entity_option) => entity_option,
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot read kb_tokens id '{}' on sqlite: {}",
|
||||
token_id, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => {
|
||||
let dto_result = crate::KbTokenDto::try_from(entity);
|
||||
match dto_result {
|
||||
Ok(dto) => return Ok(Some(dto)),
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
},
|
||||
None => return Ok(None),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists all normalized token rows ordered by mint.
|
||||
pub async fn list_tokens(
|
||||
@@ -152,7 +203,7 @@ ORDER BY mint ASC, id ASC
|
||||
"cannot list kb_tokens on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -163,7 +214,161 @@ ORDER BY mint ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists token rows whose display or mint metadata is incomplete.
|
||||
pub async fn list_tokens_missing_metadata(
|
||||
database: &crate::KbDatabase,
|
||||
limit: std::option::Option<i64>,
|
||||
) -> Result<std::vec::Vec<crate::KbTokenDto>, crate::KbError> {
|
||||
match database.connection() {
|
||||
crate::KbDatabaseConnection::Sqlite(pool) => {
|
||||
let entities_result = match limit {
|
||||
Some(limit) => {
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbTokenEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
mint,
|
||||
symbol,
|
||||
name,
|
||||
decimals,
|
||||
token_program,
|
||||
is_quote_token,
|
||||
first_seen_at,
|
||||
updated_at
|
||||
FROM kb_tokens
|
||||
WHERE symbol IS NULL
|
||||
OR trim(symbol) = ''
|
||||
OR name IS NULL
|
||||
OR trim(name) = ''
|
||||
OR decimals IS NULL
|
||||
OR token_program IS NULL
|
||||
OR trim(token_program) = ''
|
||||
ORDER BY updated_at ASC, id ASC
|
||||
LIMIT ?
|
||||
"#,
|
||||
)
|
||||
.bind(limit)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
},
|
||||
None => {
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::KbTokenEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
mint,
|
||||
symbol,
|
||||
name,
|
||||
decimals,
|
||||
token_program,
|
||||
is_quote_token,
|
||||
first_seen_at,
|
||||
updated_at
|
||||
FROM kb_tokens
|
||||
WHERE symbol IS NULL
|
||||
OR trim(symbol) = ''
|
||||
OR name IS NULL
|
||||
OR trim(name) = ''
|
||||
OR decimals IS NULL
|
||||
OR token_program IS NULL
|
||||
OR trim(token_program) = ''
|
||||
ORDER BY updated_at ASC, id ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
},
|
||||
};
|
||||
let entities = match entities_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot list kb_tokens missing metadata on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
let dto_result = crate::KbTokenDto::try_from(entity);
|
||||
let dto = match dto_result {
|
||||
Ok(dto) => dto,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
async fn make_database() -> std::sync::Arc<crate::KbDatabase> {
|
||||
let tempdir_result = tempfile::tempdir();
|
||||
let tempdir = match tempdir_result {
|
||||
Ok(tempdir) => tempdir,
|
||||
Err(error) => panic!("tempdir must succeed: {}", error),
|
||||
};
|
||||
let database_path = tempdir.path().join("token_query.sqlite3");
|
||||
let config = crate::KbDatabaseConfig {
|
||||
enabled: true,
|
||||
backend: crate::KbDatabaseBackend::Sqlite,
|
||||
sqlite: crate::KbSqliteDatabaseConfig {
|
||||
path: database_path.to_string_lossy().to_string(),
|
||||
create_if_missing: true,
|
||||
busy_timeout_ms: 5000,
|
||||
max_connections: 1,
|
||||
auto_initialize_schema: true,
|
||||
use_wal: true,
|
||||
},
|
||||
};
|
||||
let database_result = crate::KbDatabase::connect_and_initialize(&config).await;
|
||||
let database = match database_result {
|
||||
Ok(database) => database,
|
||||
Err(error) => panic!("database init must succeed: {}", error),
|
||||
};
|
||||
return std::sync::Arc::new(database);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn list_tokens_missing_metadata_only_returns_incomplete_rows() {
|
||||
let database = make_database().await;
|
||||
let incomplete = crate::KbTokenDto::new(
|
||||
"IncompleteMint111".to_string(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
crate::SPL_TOKEN_PROGRAM_ID.to_string(),
|
||||
false,
|
||||
);
|
||||
let complete = crate::KbTokenDto::new(
|
||||
"CompleteMint111".to_string(),
|
||||
Some("CMP".to_string()),
|
||||
Some("Complete".to_string()),
|
||||
Some(6),
|
||||
crate::SPL_TOKEN_PROGRAM_ID.to_string(),
|
||||
false,
|
||||
);
|
||||
let incomplete_result = crate::upsert_token(database.as_ref(), &incomplete).await;
|
||||
if let Err(error) = incomplete_result {
|
||||
panic!("incomplete token upsert must succeed: {}", error);
|
||||
}
|
||||
let complete_result = crate::upsert_token(database.as_ref(), &complete).await;
|
||||
if let Err(error) = complete_result {
|
||||
panic!("complete token upsert must succeed: {}", error);
|
||||
}
|
||||
let missing_result = crate::list_tokens_missing_metadata(database.as_ref(), None).await;
|
||||
let missing = match missing_result {
|
||||
Ok(missing) => missing,
|
||||
Err(error) => panic!("missing metadata list must succeed: {}", error),
|
||||
};
|
||||
assert_eq!(missing.len(), 1);
|
||||
assert_eq!(missing[0].mint, "IncompleteMint111");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ pub async fn upsert_token_burn_event(
|
||||
"cannot convert token burn event slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -78,13 +78,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_token_burn_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_token_burn_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ LIMIT ?
|
||||
"cannot list kb_token_burn_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -137,8 +139,8 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,13 +167,7 @@ mod tests {
|
||||
.expect("database init must succeed");
|
||||
let dex_id = crate::upsert_dex(
|
||||
&database,
|
||||
&crate::KbDexDto::new(
|
||||
"raydium".to_string(),
|
||||
"Raydium".to_string(),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
),
|
||||
&crate::KbDexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
|
||||
)
|
||||
.await
|
||||
.expect("dex upsert must succeed");
|
||||
@@ -299,9 +295,7 @@ mod tests {
|
||||
assert!(liquidity_id > 0);
|
||||
assert!(mint_id > 0);
|
||||
assert!(burn_id > 0);
|
||||
let swaps = crate::list_recent_swaps(&database, 10)
|
||||
.await
|
||||
.expect("swaps list must succeed");
|
||||
let swaps = crate::list_recent_swaps(&database, 10).await.expect("swaps list must succeed");
|
||||
let liquidity_events = crate::list_recent_liquidity_events(&database, 10)
|
||||
.await
|
||||
.expect("liquidity list must succeed");
|
||||
|
||||
@@ -17,9 +17,9 @@ pub async fn upsert_token_mint_event(
|
||||
"cannot convert token mint event slot '{}' to i64: {}",
|
||||
slot, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
match database.connection() {
|
||||
@@ -78,13 +78,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_token_mint_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_token_mint_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
|
||||
dto.signature, dto.instruction_index, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ LIMIT ?
|
||||
"cannot list kb_token_mint_events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -137,7 +139,7 @@ LIMIT ?
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,13 +90,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_trade_events id for decoded_event_id '{}' on sqlite: {}",
|
||||
dto.decoded_event_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_trade_events id for decoded_event_id '{}' on sqlite: {}",
|
||||
dto.decoded_event_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,13 +146,13 @@ LIMIT 1
|
||||
"cannot read kb_trade_events by decoded_event_id '{}' on sqlite: {}",
|
||||
decoded_event_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbTradeEventDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbTradeEventDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +200,7 @@ ORDER BY created_at ASC, id ASC
|
||||
"cannot list kb_trade_events by pair_id '{}' on sqlite: {}",
|
||||
pair_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -209,8 +211,8 @@ ORDER BY created_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +260,7 @@ ORDER BY id ASC
|
||||
"cannot list kb_trade_events by transaction_id '{}' on sqlite: {}",
|
||||
transaction_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -269,15 +271,15 @@ ORDER BY id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_trade_side_to_string(value: crate::KbSwapTradeSide) -> &'static str {
|
||||
match value {
|
||||
crate::KbSwapTradeSide::BuyBase => "BuyBase",
|
||||
crate::KbSwapTradeSide::SellBase => "SellBase",
|
||||
crate::KbSwapTradeSide::Unknown => "Unknown",
|
||||
crate::KbSwapTradeSide::BuyBase => return "BuyBase",
|
||||
crate::KbSwapTradeSide::SellBase => return "SellBase",
|
||||
crate::KbSwapTradeSide::Unknown => return "Unknown",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +47,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallets id for address '{}' on sqlite: {}",
|
||||
dto.address, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallets id for address '{}' on sqlite: {}",
|
||||
dto.address, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +89,13 @@ LIMIT 1
|
||||
"cannot read kb_wallets '{}' on sqlite: {}",
|
||||
address, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbWalletDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbWalletDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ ORDER BY address ASC
|
||||
"cannot list kb_wallets on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -135,7 +137,7 @@ ORDER BY address ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +76,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallet_holdings id for wallet_id '{}' token_id '{}' on sqlite: {}",
|
||||
dto.wallet_id, dto.token_id, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallet_holdings id for wallet_id '{}' token_id '{}' on sqlite: {}",
|
||||
dto.wallet_id, dto.token_id, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,13 +130,13 @@ LIMIT 1
|
||||
"cannot read kb_wallet_holdings by wallet_id '{}' token_id '{}' on sqlite: {}",
|
||||
wallet_id, token_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbWalletHoldingDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbWalletHoldingDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ ORDER BY token_id ASC, id ASC
|
||||
"cannot list kb_wallet_holdings by wallet_id '{}' on sqlite: {}",
|
||||
wallet_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -189,7 +191,7 @@ ORDER BY token_id ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +60,15 @@ LIMIT 1
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => Ok(id),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallet_participations id for unique_key '{}' on sqlite: {}",
|
||||
dto.unique_key, error
|
||||
))),
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot fetch kb_wallet_participations id for unique_key '{}' on sqlite: {}",
|
||||
dto.unique_key, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,13 +109,13 @@ LIMIT 1
|
||||
"cannot read kb_wallet_participations by unique_key '{}' on sqlite: {}",
|
||||
unique_key, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
match entity_option {
|
||||
Some(entity) => crate::KbWalletParticipationDto::try_from(entity).map(Some),
|
||||
None => Ok(None),
|
||||
Some(entity) => return crate::KbWalletParticipationDto::try_from(entity).map(Some),
|
||||
None => return Ok(None),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +156,7 @@ ORDER BY created_at ASC, id ASC
|
||||
"cannot list kb_wallet_participations by wallet_id '{}' on sqlite: {}",
|
||||
wallet_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -165,8 +167,8 @@ ORDER BY created_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +209,7 @@ ORDER BY created_at ASC, id ASC
|
||||
"cannot list kb_wallet_participations by pool_id '{}' on sqlite: {}",
|
||||
pool_id, error
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
@@ -218,7 +220,7 @@ ORDER BY created_at ASC, id ASC
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
Ok(dtos)
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,12 +8,10 @@ pub(crate) fn sqlite_database_url_from_config(
|
||||
) -> Result<std::string::String, crate::KbError> {
|
||||
let path = config.sqlite.path.trim();
|
||||
if path.is_empty() {
|
||||
return Err(crate::KbError::Config(
|
||||
"database.sqlite.path must not be empty".to_string(),
|
||||
));
|
||||
return Err(crate::KbError::Config("database.sqlite.path must not be empty".to_string()));
|
||||
}
|
||||
let database_path = config.sqlite.path_buf();
|
||||
Ok(format!("sqlite://{}", database_path.display()))
|
||||
return Ok(format!("sqlite://{}", database_path.display()));
|
||||
}
|
||||
|
||||
/// Opens a SQLite pool according to configuration.
|
||||
@@ -22,9 +20,7 @@ pub(crate) async fn connect_sqlite(
|
||||
) -> Result<sqlx::SqlitePool, crate::KbError> {
|
||||
let path = config.sqlite.path.trim();
|
||||
if path.is_empty() {
|
||||
return Err(crate::KbError::Config(
|
||||
"database.sqlite.path must not be empty".to_string(),
|
||||
));
|
||||
return Err(crate::KbError::Config("database.sqlite.path must not be empty".to_string()));
|
||||
}
|
||||
if config.sqlite.max_connections == 0 {
|
||||
return Err(crate::KbError::Config(
|
||||
@@ -49,9 +45,7 @@ pub(crate) async fn connect_sqlite(
|
||||
.filename(&database_path)
|
||||
.create_if_missing(config.sqlite.create_if_missing)
|
||||
.foreign_keys(true)
|
||||
.busy_timeout(std::time::Duration::from_millis(
|
||||
config.sqlite.busy_timeout_ms,
|
||||
));
|
||||
.busy_timeout(std::time::Duration::from_millis(config.sqlite.busy_timeout_ms));
|
||||
if config.sqlite.use_wal {
|
||||
connect_options = connect_options.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal);
|
||||
}
|
||||
@@ -59,10 +53,13 @@ pub(crate) async fn connect_sqlite(
|
||||
sqlx::sqlite::SqlitePoolOptions::new().max_connections(config.sqlite.max_connections);
|
||||
let connect_result = pool_options.connect_with(connect_options).await;
|
||||
match connect_result {
|
||||
Ok(pool) => Ok(pool),
|
||||
Err(error) => Err(crate::KbError::Db(format!(
|
||||
"cannot open sqlite database '{}': {}",
|
||||
database_path.display(), error
|
||||
))),
|
||||
Ok(pool) => return Ok(pool),
|
||||
Err(error) => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"cannot open sqlite database '{}': {}",
|
||||
database_path.display(),
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,28 +21,28 @@ impl KbAnalysisSignalSeverity {
|
||||
/// Converts the severity to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Info => 0,
|
||||
Self::Low => 1,
|
||||
Self::Medium => 2,
|
||||
Self::High => 3,
|
||||
Self::Critical => 4,
|
||||
Self::Info => return 0,
|
||||
Self::Low => return 1,
|
||||
Self::Medium => return 2,
|
||||
Self::High => return 3,
|
||||
Self::Critical => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a severity from its stable integer representation.
|
||||
pub fn from_i16(
|
||||
value: i16,
|
||||
) -> Result<Self, crate::KbError> {
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Info),
|
||||
1 => Ok(Self::Low),
|
||||
2 => Ok(Self::Medium),
|
||||
3 => Ok(Self::High),
|
||||
4 => Ok(Self::Critical),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbAnalysisSignalSeverity value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Info),
|
||||
1 => return Ok(Self::Low),
|
||||
2 => return Ok(Self::Medium),
|
||||
3 => return Ok(Self::High),
|
||||
4 => return Ok(Self::Critical),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbAnalysisSignalSeverity value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,20 +15,22 @@ impl KbLiquidityEventKind {
|
||||
/// Converts the event kind to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Add => 0,
|
||||
Self::Remove => 1,
|
||||
Self::Add => return 0,
|
||||
Self::Remove => return 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores an event kind from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Add),
|
||||
1 => Ok(Self::Remove),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbLiquidityEventKind value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Add),
|
||||
1 => return Ok(Self::Remove),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbLiquidityEventKind value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,28 @@ impl KbObservationSourceKind {
|
||||
/// Converts the source kind to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::HttpRpc => 0,
|
||||
Self::WsRpc => 1,
|
||||
Self::Grpc => 2,
|
||||
Self::Dex => 3,
|
||||
Self::Other => 4,
|
||||
Self::HttpRpc => return 0,
|
||||
Self::WsRpc => return 1,
|
||||
Self::Grpc => return 2,
|
||||
Self::Dex => return 3,
|
||||
Self::Other => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a source kind from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::HttpRpc),
|
||||
1 => Ok(Self::WsRpc),
|
||||
2 => Ok(Self::Grpc),
|
||||
3 => Ok(Self::Dex),
|
||||
4 => Ok(Self::Other),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbObservationSourceKind value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::HttpRpc),
|
||||
1 => return Ok(Self::WsRpc),
|
||||
2 => return Ok(Self::Grpc),
|
||||
3 => return Ok(Self::Dex),
|
||||
4 => return Ok(Self::Other),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbObservationSourceKind value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,26 @@ impl KbObservedTokenStatus {
|
||||
/// Converts the status to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::New => 0,
|
||||
Self::Active => 1,
|
||||
Self::Ignored => 2,
|
||||
Self::Blocked => 3,
|
||||
Self::New => return 0,
|
||||
Self::Active => return 1,
|
||||
Self::Ignored => return 2,
|
||||
Self::Blocked => return 3,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a status from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::New),
|
||||
1 => Ok(Self::Active),
|
||||
2 => Ok(Self::Ignored),
|
||||
3 => Ok(Self::Blocked),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbObservedTokenStatus value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::New),
|
||||
1 => return Ok(Self::Active),
|
||||
2 => return Ok(Self::Ignored),
|
||||
3 => return Ok(Self::Blocked),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbObservedTokenStatus value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
// file: kb_lib/src/db/types/pool_kind.rs
|
||||
|
||||
//! Pool kind.
|
||||
@@ -22,28 +21,23 @@ impl KbPoolKind {
|
||||
/// Converts the kind to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Unknown => 0,
|
||||
Self::Amm => 1,
|
||||
Self::Clmm => 2,
|
||||
Self::BondingCurve => 3,
|
||||
Self::OrderBook => 4,
|
||||
Self::Unknown => return 0,
|
||||
Self::Amm => return 1,
|
||||
Self::Clmm => return 2,
|
||||
Self::BondingCurve => return 3,
|
||||
Self::OrderBook => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a kind from its stable integer representation.
|
||||
pub fn from_i16(
|
||||
value: i16,
|
||||
) -> Result<Self, crate::KbError> {
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Unknown),
|
||||
1 => Ok(Self::Amm),
|
||||
2 => Ok(Self::Clmm),
|
||||
3 => Ok(Self::BondingCurve),
|
||||
4 => Ok(Self::OrderBook),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbPoolKind value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Unknown),
|
||||
1 => return Ok(Self::Amm),
|
||||
2 => return Ok(Self::Clmm),
|
||||
3 => return Ok(Self::BondingCurve),
|
||||
4 => return Ok(Self::OrderBook),
|
||||
_ => return Err(crate::KbError::Db(format!("invalid KbPoolKind value: {}", value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,23 @@ impl KbPoolStatus {
|
||||
/// Converts the status to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Unknown => 0,
|
||||
Self::Pending => 1,
|
||||
Self::Active => 2,
|
||||
Self::Inactive => 3,
|
||||
Self::Closed => 4,
|
||||
Self::Unknown => return 0,
|
||||
Self::Pending => return 1,
|
||||
Self::Active => return 2,
|
||||
Self::Inactive => return 3,
|
||||
Self::Closed => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a status from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Unknown),
|
||||
1 => Ok(Self::Pending),
|
||||
2 => Ok(Self::Active),
|
||||
3 => Ok(Self::Inactive),
|
||||
4 => Ok(Self::Closed),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbPoolStatus value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Unknown),
|
||||
1 => return Ok(Self::Pending),
|
||||
2 => return Ok(Self::Active),
|
||||
3 => return Ok(Self::Inactive),
|
||||
4 => return Ok(Self::Closed),
|
||||
_ => return Err(crate::KbError::Db(format!("invalid KbPoolStatus value: {}", value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,25 @@ impl KbPoolTokenRole {
|
||||
/// Converts the role to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Base => 0,
|
||||
Self::Quote => 1,
|
||||
Self::LpMint => 2,
|
||||
Self::Reserve => 3,
|
||||
Self::Other => 4,
|
||||
Self::Base => return 0,
|
||||
Self::Quote => return 1,
|
||||
Self::LpMint => return 2,
|
||||
Self::Reserve => return 3,
|
||||
Self::Other => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a role from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Base),
|
||||
1 => Ok(Self::Quote),
|
||||
2 => Ok(Self::LpMint),
|
||||
3 => Ok(Self::Reserve),
|
||||
4 => Ok(Self::Other),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbPoolTokenRole value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Base),
|
||||
1 => return Ok(Self::Quote),
|
||||
2 => return Ok(Self::LpMint),
|
||||
3 => return Ok(Self::Reserve),
|
||||
4 => return Ok(Self::Other),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!("invalid KbPoolTokenRole value: {}", value)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,28 @@ impl KbDbRuntimeEventLevel {
|
||||
/// Converts the level to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Trace => 0,
|
||||
Self::Debug => 1,
|
||||
Self::Info => 2,
|
||||
Self::Warn => 3,
|
||||
Self::Error => 4,
|
||||
Self::Trace => return 0,
|
||||
Self::Debug => return 1,
|
||||
Self::Info => return 2,
|
||||
Self::Warn => return 3,
|
||||
Self::Error => return 4,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a level from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Trace),
|
||||
1 => Ok(Self::Debug),
|
||||
2 => Ok(Self::Info),
|
||||
3 => Ok(Self::Warn),
|
||||
4 => Ok(Self::Error),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbDbRuntimeEventLevel value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Trace),
|
||||
1 => return Ok(Self::Debug),
|
||||
2 => return Ok(Self::Info),
|
||||
3 => return Ok(Self::Warn),
|
||||
4 => return Ok(Self::Error),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbDbRuntimeEventLevel value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,22 +17,24 @@ impl KbSwapTradeSide {
|
||||
/// Converts the trade side to its stable integer representation.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
match self {
|
||||
Self::Unknown => 0,
|
||||
Self::BuyBase => 1,
|
||||
Self::SellBase => 2,
|
||||
Self::Unknown => return 0,
|
||||
Self::BuyBase => return 1,
|
||||
Self::SellBase => return 2,
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores a trade side from its stable integer representation.
|
||||
pub fn from_i16(value: i16) -> Result<Self, crate::KbError> {
|
||||
match value {
|
||||
0 => Ok(Self::Unknown),
|
||||
1 => Ok(Self::BuyBase),
|
||||
2 => Ok(Self::SellBase),
|
||||
_ => Err(crate::KbError::Db(format!(
|
||||
"invalid KbSwapTradeSide value: {}",
|
||||
value
|
||||
))),
|
||||
0 => return Ok(Self::Unknown),
|
||||
1 => return Ok(Self::BuyBase),
|
||||
2 => return Ok(Self::SellBase),
|
||||
_ => {
|
||||
return Err(crate::KbError::Db(format!(
|
||||
"invalid KbSwapTradeSide value: {}",
|
||||
value
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user