Skip to content

Commit

Permalink
Add function to see latest non voting transactions (#98)
Browse files Browse the repository at this point in the history
* Add function to see latest non-voting transactions

* Nits
  • Loading branch information
pmantica11 authored May 14, 2024
1 parent 8d429a0 commit ba5b50b
Show file tree
Hide file tree
Showing 26 changed files with 609 additions and 91 deletions.
36 changes: 21 additions & 15 deletions src/api/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use sqlx::{postgres::PgPoolOptions, Executor};
use utoipa::openapi::{ObjectBuilder, RefOr, Schema, SchemaType};
use utoipa::ToSchema;

use crate::api::method::utils::GetNonPaginatedSignaturesResponse;
use crate::common::typedefs::unsigned_integer::UnsignedInteger;

use super::method::get_compressed_account::AccountResponse;
Expand All @@ -16,9 +17,7 @@ use super::method::get_compressed_token_balances_by_owner::{
get_compressed_token_balances_by_owner, GetCompressedTokenBalancesByOwnerRequest,
TokenBalancesResponse,
};
use super::method::get_compression_signatures_for_account::{
get_compression_signatures_for_account, GetCompressionSignaturesForAccountResponse,
};
use super::method::get_compression_signatures_for_account::get_compression_signatures_for_account;
use super::method::get_compression_signatures_for_address::{
get_compression_signatures_for_address, GetCompressionSignaturesForAddressRequest,
};
Expand All @@ -28,12 +27,12 @@ use super::method::get_compression_signatures_for_owner::{
use super::method::get_compression_signatures_for_token_owner::{
get_compression_signatures_for_token_owner, GetCompressionSignaturesForTokenOwnerRequest,
};
use super::method::get_latest_compression_signatures::{
get_latest_compression_signatures, GetLatestCompressionSignaturesRequest,
};
use super::method::get_latest_compression_signatures::get_latest_compression_signatures;
use super::method::get_latest_non_voting_signatures::get_latest_non_voting_signatures;
use super::method::get_transaction_with_compression_info::{
get_transaction_with_compression_info, GetTransactionRequest, GetTransactionResponse,
};
use super::method::utils::GetLatestSignaturesRequest;
use super::method::utils::{AccountBalanceResponse, GetPaginatedSignaturesResponse, HashRequest};
use super::{
error::PhotonApiError,
Expand Down Expand Up @@ -215,7 +214,7 @@ impl PhotonApi {
pub async fn get_compression_signatures_for_account(
&self,
request: HashRequest,
) -> Result<GetCompressionSignaturesForAccountResponse, PhotonApiError> {
) -> Result<GetNonPaginatedSignaturesResponse, PhotonApiError> {
get_compression_signatures_for_account(self.db_conn.as_ref(), request).await
}

Expand Down Expand Up @@ -254,11 +253,18 @@ impl PhotonApi {

pub async fn get_latest_compression_signatures(
&self,
request: GetLatestCompressionSignaturesRequest,
request: GetLatestSignaturesRequest,
) -> Result<GetPaginatedSignaturesResponse, PhotonApiError> {
get_latest_compression_signatures(self.db_conn.as_ref(), request).await
}

pub async fn get_latest_non_voting_signatures(
&self,
request: GetLatestSignaturesRequest,
) -> Result<GetNonPaginatedSignaturesResponse, PhotonApiError> {
get_latest_non_voting_signatures(self.db_conn.as_ref(), request).await
}

pub fn method_api_specs() -> Vec<OpenApiSpec> {
vec![
OpenApiSpec {
Expand Down Expand Up @@ -316,11 +322,6 @@ impl PhotonApi {
request: Some(GetCompressedTokenBalancesByOwnerRequest::schema().1),
response: TokenBalancesResponse::schema().1,
},
OpenApiSpec {
name: "getCompressionSignaturesForAccount".to_string(),
request: Some(HashRequest::schema().1),
response: GetCompressionSignaturesForAccountResponse::schema().1,
},
OpenApiSpec {
name: "getTransactionWithCompressionInfo".to_string(),
request: Some(GetTransactionRequest::schema().1),
Expand All @@ -329,7 +330,7 @@ impl PhotonApi {
OpenApiSpec {
name: "getCompressionSignaturesForAccount".to_string(),
request: Some(HashRequest::schema().1),
response: GetCompressionSignaturesForAccountResponse::schema().1,
response: GetNonPaginatedSignaturesResponse::schema().1,
},
OpenApiSpec {
name: "getCompressionSignaturesForAddress".to_string(),
Expand All @@ -348,9 +349,14 @@ impl PhotonApi {
},
OpenApiSpec {
name: "getLatestCompressionSignatures".to_string(),
request: Some(GetLatestCompressionSignaturesRequest::schema().1),
request: Some(GetLatestSignaturesRequest::schema().1),
response: GetPaginatedSignaturesResponse::schema().1,
},
OpenApiSpec {
name: "getLatestNonVotingSignatures".to_string(),
request: Some(GetLatestSignaturesRequest::schema().1),
response: GetNonPaginatedSignaturesResponse::schema().1,
},
OpenApiSpec {
name: "getIndexerHealth".to_string(),
request: None,
Expand Down
18 changes: 5 additions & 13 deletions src/api/method/get_compression_signatures_for_account.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use super::{
super::error::PhotonApiError,
utils::{
search_for_signatures, Context, HashRequest, SignatureFilter, SignatureInfoList,
SignatureSearchType,
search_for_signatures, Context, GetNonPaginatedSignaturesResponse, HashRequest,
SignatureFilter, SignatureInfoList, SignatureSearchType,
},
};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
// We do not use generics to simplify documentation generation.
pub struct GetCompressionSignaturesForAccountResponse {
pub context: Context,
pub value: SignatureInfoList,
}

pub async fn get_compression_signatures_for_account(
conn: &DatabaseConnection,
request: HashRequest,
) -> Result<GetCompressionSignaturesForAccountResponse, PhotonApiError> {
) -> Result<GetNonPaginatedSignaturesResponse, PhotonApiError> {
let context = Context::extract(conn).await?;
let hash = request.hash;

let signatures = search_for_signatures(
conn,
SignatureSearchType::Standard,
Some(SignatureFilter::Account(hash)),
true,
None,
None,
)
Expand All @@ -47,7 +39,7 @@ pub async fn get_compression_signatures_for_account(
));
}

Ok(GetCompressionSignaturesForAccountResponse {
Ok(GetNonPaginatedSignaturesResponse {
value: SignatureInfoList { items: signatures },
context,
})
Expand Down
1 change: 1 addition & 0 deletions src/api/method/get_compression_signatures_for_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub async fn get_compression_signatures_for_address(
conn,
SignatureSearchType::Standard,
Some(SignatureFilter::Address(request.address)),
true,
request.cursor,
request.limit,
)
Expand Down
1 change: 1 addition & 0 deletions src/api/method/get_compression_signatures_for_owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub async fn get_compression_signatures_for_owner(
conn,
SignatureSearchType::Standard,
Some(SignatureFilter::Owner(request.owner)),
true,
request.cursor,
request.limit,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub async fn get_compression_signatures_for_token_owner(
conn,
SignatureSearchType::Token,
Some(SignatureFilter::Owner(request.owner)),
true,
request.cursor,
request.limit,
)
Expand Down
15 changes: 4 additions & 11 deletions src/api/method/get_latest_compression_signatures.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
use super::utils::GetPaginatedSignaturesResponse;
use super::utils::{GetLatestSignaturesRequest, GetPaginatedSignaturesResponse};
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use super::{
super::error::PhotonApiError,
utils::{search_for_signatures, Context, Limit, SignatureSearchType},
utils::{search_for_signatures, Context, SignatureSearchType},
};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema, Default)]
pub struct GetLatestCompressionSignaturesRequest {
pub limit: Option<Limit>,
pub cursor: Option<String>,
}

pub async fn get_latest_compression_signatures(
conn: &DatabaseConnection,
request: GetLatestCompressionSignaturesRequest,
request: GetLatestSignaturesRequest,
) -> Result<GetPaginatedSignaturesResponse, PhotonApiError> {
let context = Context::extract(conn).await?;

let signatures = search_for_signatures(
conn,
SignatureSearchType::Standard,
None,
true,
request.cursor,
request.limit,
)
Expand Down
31 changes: 31 additions & 0 deletions src/api/method/get_latest_non_voting_signatures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use super::utils::{GetLatestSignaturesRequest, GetNonPaginatedSignaturesResponse};
use sea_orm::DatabaseConnection;

use super::{
super::error::PhotonApiError,
utils::{search_for_signatures, Context, SignatureSearchType},
};

pub async fn get_latest_non_voting_signatures(
conn: &DatabaseConnection,
request: GetLatestSignaturesRequest,
) -> Result<GetNonPaginatedSignaturesResponse, PhotonApiError> {
let context = Context::extract(conn).await?;

let signatures = search_for_signatures(
conn,
SignatureSearchType::Standard,
None,
false,
request.cursor,
request.limit,
)
.await?;

Ok(GetNonPaginatedSignaturesResponse {
value: super::utils::SignatureInfoList {
items: signatures.items,
},
context,
})
}
1 change: 1 addition & 0 deletions src/api/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod get_compression_signatures_for_token_owner;
pub mod get_indexer_health;
pub mod get_indexer_slot;
pub mod get_latest_compression_signatures;
pub mod get_latest_non_voting_signatures;
pub mod get_multiple_compressed_account_proofs;
pub mod get_multiple_compressed_accounts;
pub mod get_transaction_with_compression_info;
Expand Down
31 changes: 28 additions & 3 deletions src/api/method/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ fn compute_cursor_filter(
fn compute_raw_sql_query_and_args(
search_type: SignatureSearchType,
signature_filter: Option<SignatureFilter>,
only_compressed: bool,
cursor: Option<String>,
limit: u64,
) -> Result<(String, Vec<Value>), PhotonApiError> {
Expand Down Expand Up @@ -589,18 +590,23 @@ fn compute_raw_sql_query_and_args(
"Token search requires a filter".to_string(),
));
}
let compression_filter = if only_compressed {
"AND transactions.uses_compression = true"
} else {
""
};
let (cursor_filter, cursor_args) = compute_cursor_filter(cursor, 0)?;
let raw_sql = format!(
"
SELECT transactions.signature, transactions.slot, blocks.block_time
FROM transactions
JOIN blocks ON transactions.slot = blocks.slot
{cursor_filter}
{compression_filter}
ORDER BY transactions.slot DESC, transactions.signature DESC
LIMIT {limit}
"
);

Ok((raw_sql, cursor_args))
}
}
Expand All @@ -610,12 +616,18 @@ pub async fn search_for_signatures(
conn: &DatabaseConnection,
search_type: SignatureSearchType,
signature_filter: Option<SignatureFilter>,
only_compressed: bool,
cursor: Option<String>,
limit: Option<Limit>,
) -> Result<PaginatedSignatureInfoList, PhotonApiError> {
let limit = limit.unwrap_or_default().0;
let (raw_sql, args) =
compute_raw_sql_query_and_args(search_type, signature_filter, cursor, limit)?;
let (raw_sql, args) = compute_raw_sql_query_and_args(
search_type,
signature_filter,
only_compressed,
cursor,
limit,
)?;

let signatures: Vec<SignatureInfoModel> = SignatureInfoModel::find_by_statement(
Statement::from_sql_and_values(conn.get_database_backend(), &raw_sql, args.clone()),
Expand Down Expand Up @@ -673,3 +685,16 @@ pub struct AccountBalanceResponse {
pub context: Context,
pub value: UnsignedInteger,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema, Default)]
pub struct GetLatestSignaturesRequest {
pub limit: Option<Limit>,
pub cursor: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
// We do not use generics to simplify documentation generation.
pub struct GetNonPaginatedSignaturesResponse {
pub context: Context,
pub value: SignatureInfoList,
}
12 changes: 12 additions & 0 deletions src/api/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,17 @@ fn build_rpc_module(
},
)?;

module.register_async_method(
"getLatestNonVotingSignatures",
|rpc_params, rpc_context| async move {
let ApiAndIndexer { api, indexer } = rpc_context.as_ref();
conditionally_index_latest_blocks(indexer).await;
let payload = rpc_params.parse()?;
api.get_latest_non_voting_signatures(payload)
.await
.map_err(Into::into)
},
)?;

Ok(module)
}
1 change: 1 addition & 0 deletions src/dao/generated/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub signature: Vec<u8>,
pub slot: i64,
pub uses_compression: bool,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand Down
2 changes: 1 addition & 1 deletion src/ingester/parser/indexer_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub enum ChangelogEvent {

/// Node of the Merkle path with an index representing the position in a
/// non-sparse Merkle tree.
#[derive(BorshDeserialize, BorshSerialize, Debug, Clone)]
#[derive(BorshDeserialize, BorshSerialize, Debug, Clone, PartialEq, Eq)]
pub struct PathNode {
pub node: [u8; 32],
pub index: u32,
Expand Down
Loading

0 comments on commit ba5b50b

Please sign in to comment.