Skip to content

Commit

Permalink
feat: rpc get proposal snapshots on specific block
Browse files Browse the repository at this point in the history
  • Loading branch information
Tguntenaar committed Nov 20, 2024
1 parent e31db70 commit cf6384f
Show file tree
Hide file tree
Showing 13 changed files with 174 additions and 35 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,37 @@ impl DB {
}
}

// TODO Remove this once we go in production or put it behind authentication or a flag
pub async fn remove_rfp_snapshots_by_rfp_id(&self, rfp_id: i32) -> anyhow::Result<()> {
sqlx::query!(r#"DELETE FROM rfp_snapshots WHERE rfp_id = $1"#, rfp_id)
.execute(&self.0)
.await?;
Ok(())
}

// TODO Remove this once we go in production or put it behind authentication or a flag
pub async fn remove_proposal_snapshots_by_id(&self, proposal_id: i32) -> anyhow::Result<()> {
sqlx::query!(
r#"DELETE FROM proposal_snapshots WHERE proposal_id = $1"#,
proposal_id
)
.execute(&self.0)
.await?;
Ok(())
}

// TODO Remove this once we go in production or put it behind authentication or a flag
pub async fn remove_all_snapshots(&self) -> anyhow::Result<()> {
sqlx::query!(r#"DELETE FROM proposal_snapshots"#)
.execute(&self.0)
.await?;

sqlx::query!(r#"DELETE FROM rfp_snapshots"#)
.execute(&self.0)
.await?;
Ok(())
}

pub async fn insert_rfp_snapshot(
tx: &mut Transaction<'static, Postgres>,
snapshot: &RfpSnapshotRecord,
Expand Down Expand Up @@ -700,6 +731,8 @@ impl DB {
rfp_snapshots rfp
WHERE
rfp.rfp_id = $1
ORDER BY
rfp.ts DESC
"#;

// Execute the data query
Expand Down
35 changes: 32 additions & 3 deletions src/entrypoints/proposal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::types::PaginatedResponse;
use crate::{nearblocks_client, separate_number_and_text};
use devhub_shared::proposal::VersionedProposal;
use near_account_id::AccountId;
use rocket::delete;
use rocket::serde::json::Json;
use rocket::{get, http::Status, State};
use std::convert::TryInto;
Expand Down Expand Up @@ -129,7 +130,7 @@ async fn get_proposals(

match nearblocks_unwrapped.txns.last() {
Some(transaction) => {
let timestamp_nano: i64 = transaction.block_timestamp.parse().unwrap();
let timestamp_nano: i64 = transaction.receipt_block.block_timestamp;

db.set_last_updated_info(timestamp_nano, transaction.block.block_height)
.await
Expand Down Expand Up @@ -186,6 +187,18 @@ async fn set_timestamp(block_height: i64, db: &State<DB>) -> Result<(), Status>
}
}

// TODO remove after testing
#[get("/info/clean")]
async fn clean(db: &State<DB>) -> Result<(), Status> {
match db.remove_all_snapshots().await {
Ok(()) => Ok(()),
Err(e) => {
eprintln!("Error cleaning snapshots: {:?}", e);
Err(Status::InternalServerError)
}
}
}

#[get("/info")]
async fn get_timestamp(db: &State<DB>) -> Result<Json<(i64, i64)>, Status> {
let (timestamp, block_height) = db.get_last_updated_info().await.unwrap();
Expand All @@ -210,6 +223,18 @@ async fn get_proposal(
}
}

// TODO Remove this once we go in production or put it behind authentication or a flag
#[delete("/<proposal_id>/snapshots")]
async fn remove_proposal_snapshots_by_id(proposal_id: i32, db: &State<DB>) -> Result<(), Status> {
match db.remove_proposal_snapshots_by_id(proposal_id).await {
Ok(_) => Ok(()),
Err(e) => {
eprintln!("Failed to remove proposal snapshots: {:?}", e);
Err(Status::InternalServerError)
}
}
}

pub fn stage() -> rocket::fairing::AdHoc {
// rocket
rocket::fairing::AdHoc::on_ignite("Proposal Stage", |rocket| async {
Expand All @@ -218,11 +243,15 @@ pub fn stage() -> rocket::fairing::AdHoc {
rocket
.mount(
"/proposals/",
rocket::routes![get_proposals, set_timestamp, get_timestamp, search],
rocket::routes![get_proposals, set_timestamp, get_timestamp, search, clean],
)
.mount(
"/proposal/",
rocket::routes![get_proposal, get_proposal_with_all_snapshots],
rocket::routes![
get_proposal,
get_proposal_with_all_snapshots,
remove_proposal_snapshots_by_id,
],
)
})
}
6 changes: 3 additions & 3 deletions src/entrypoints/proposal/proposal_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,21 +163,21 @@ impl ProposalBodyFields for VersionedProposalBody {
pub trait FromContractProposal {
fn from_contract_proposal(
proposal: ContractProposal,
timestamp: String,
timestamp: i64,
block_height: i64,
) -> Self;
}

impl FromContractProposal for ProposalSnapshotRecord {
fn from_contract_proposal(
proposal: ContractProposal,
timestamp: String,
timestamp: i64,
block_height: i64,
) -> Self {
ProposalSnapshotRecord {
proposal_id: proposal.id as i32,
block_height,
ts: timestamp.parse::<i64>().unwrap_or_default(),
ts: timestamp,
editor_id: proposal.snapshot.editor_id.to_string(),
social_db_post_block_height: proposal.social_db_post_block_height as i64,
labels: serde_json::Value::from(Vec::from_iter(
Expand Down
25 changes: 22 additions & 3 deletions src/entrypoints/rfp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{nearblocks_client, separate_number_and_text, timestamp_to_date_strin
use devhub_shared::rfp::VersionedRFP;
use near_account_id::AccountId;
use rocket::serde::json::Json;
use rocket::{get, http::Status, State};
use rocket::{delete, get, http::Status, State};
use std::convert::TryInto;
pub mod rfp_types;

Expand Down Expand Up @@ -130,7 +130,7 @@ async fn get_rfps(
// If it is, then we need to use the cursor from the nearblocks response
match nearblocks_unwrapped.txns.last() {
Some(transaction) => {
let timestamp_nano: i64 = transaction.block_timestamp.parse().unwrap();
let timestamp_nano: i64 = transaction.receipt_block.block_timestamp;
db.set_last_updated_info(timestamp_nano, transaction.block.block_height)
.await
.unwrap();
Expand Down Expand Up @@ -191,12 +191,31 @@ async fn get_rfp_with_snapshots(
}
}

// TODO Remove this once we go in production or put it behind authentication or a flag
#[delete("/<rfp_id>/snapshots")]
async fn remove_rfp_snapshots_by_rfp_id(rfp_id: i32, db: &State<DB>) -> Result<(), Status> {
match db.remove_rfp_snapshots_by_rfp_id(rfp_id).await {
Ok(_) => Ok(()),
Err(e) => {
eprintln!("Failed to remove rfp snapshots: {:?}", e);
Err(Status::InternalServerError)
}
}
}

pub fn stage() -> rocket::fairing::AdHoc {
rocket::fairing::AdHoc::on_ignite("Rfp Stage", |rocket| async {
println!("Rfp stage on ignite!");

rocket
.mount("/rfps/", rocket::routes![get_rfps, search])
.mount("/rfp/", rocket::routes![get_rfp, get_rfp_with_snapshots])
.mount(
"/rfp/",
rocket::routes![
get_rfp,
get_rfp_with_snapshots,
remove_rfp_snapshots_by_rfp_id
],
)
})
}
10 changes: 5 additions & 5 deletions src/entrypoints/rfp/rfp_types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::db::db_types::RfpSnapshotRecord;
use devhub_shared::rfp::RFP as ContractRFP;
pub use devhub_shared::rfp::RFP as ContractRFP;
use devhub_shared::rfp::{VersionedRFPBody, RFP};
use rocket::serde::{Deserialize, Serialize};
use rocket::FromForm;
Expand Down Expand Up @@ -32,19 +32,19 @@ pub struct SetRfpBlockHeightCallbackArgs {
}

pub trait FromContractProposal {
fn from_contract_rfp(rfp: ContractRFP, timestamp: String, block_height: i64) -> Self;
fn from_contract_rfp(rfp: ContractRFP, timestamp: i64, block_height: i64) -> Self;
}

pub trait FromContractRFP {
fn from_contract_rfp(rfp: ContractRFP, timestamp: String, block_height: i64) -> Self;
fn from_contract_rfp(rfp: ContractRFP, timestamp: i64, block_height: i64) -> Self;
}

impl FromContractRFP for RfpSnapshotRecord {
fn from_contract_rfp(rfp: ContractRFP, timestamp: String, block_height: i64) -> Self {
fn from_contract_rfp(rfp: ContractRFP, timestamp: i64, block_height: i64) -> Self {
RfpSnapshotRecord {
rfp_id: rfp.id as i32,
block_height,
ts: timestamp.parse::<i64>().unwrap_or_default(),
ts: timestamp,
editor_id: rfp.snapshot.editor_id.to_string(),
social_db_post_block_height: rfp.social_db_post_block_height as i64,
labels: serde_json::Value::from(Vec::from_iter(rfp.snapshot.labels.iter().cloned())),
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ fn rocket() -> _ {

let allowed_origins = AllowedOrigins::some_exact(&[
"http://localhost:3000",
"http://localhost:8080",
"http://127.0.0.1:8080",
"http://localhost:8080", // Playwright
"http://127.0.0.1:8080", // Local development
"https://dev.near.org",
"https://near.social",
"https://neardevhub.org",
Expand Down
21 changes: 15 additions & 6 deletions src/nearblocks_client/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ async fn handle_set_rfp_block_height_callback(

let snapshot = RfpSnapshotRecord::from_contract_rfp(
versioned_rfp.into(),
transaction.block_timestamp,
transaction.receipt_block.block_timestamp,
transaction.block.block_height,
);

Expand Down Expand Up @@ -187,9 +187,15 @@ async fn handle_edit_rfp(

let mut tx = db.begin().await.map_err(|_e| Status::InternalServerError)?;

let contract_rfp: ContractRFP = versioned_rfp.clone().into();
println!(
"RFP {} timestamp {}",
contract_rfp.id, transaction.receipt_block.block_timestamp
);

let snapshot = RfpSnapshotRecord::from_contract_rfp(
versioned_rfp.into(),
transaction.block_timestamp,
transaction.receipt_block.block_timestamp,
transaction.block.block_height,
);

Expand Down Expand Up @@ -259,7 +265,7 @@ async fn handle_set_block_height_callback(

let snapshot = ProposalSnapshotRecord::from_contract_proposal(
versioned_proposal.into(),
transaction.block_timestamp,
transaction.receipt_block.block_timestamp,
transaction.block.block_height,
);

Expand Down Expand Up @@ -301,8 +307,11 @@ async fn handle_edit_proposal(
Status::InternalServerError
})?;
println!("Updating proposal {}", id);
let versioned_proposal = match rpc_service.get_proposal(id).await {
Ok(proposal) => proposal.data,
let versioned_proposal = match rpc_service
.get_proposal_on_block(id, transaction.block.block_height)
.await
{
Ok(proposal) => proposal,
Err(e) => {
eprintln!("Failed to get proposal from RPC: {:?}", e);
return Err(Status::InternalServerError);
Expand All @@ -313,7 +322,7 @@ async fn handle_edit_proposal(

let snapshot = ProposalSnapshotRecord::from_contract_proposal(
versioned_proposal.into(),
transaction.block_timestamp,
transaction.receipt_block.block_timestamp,
transaction.block.block_height,
);

Expand Down
2 changes: 1 addition & 1 deletion src/nearblocks_client/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct Transaction {
pub struct Block {
pub block_hash: String,
pub block_height: f64,
pub block_timestamp: f64,
pub block_timestamp: i64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down
21 changes: 9 additions & 12 deletions src/rpc_service.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use base64::{engine::general_purpose, Engine as _}; // Add this import
use devhub_shared::proposal::VersionedProposal;
use devhub_shared::rfp::VersionedRFP;
use near_account_id::AccountId;
Expand Down Expand Up @@ -106,19 +105,17 @@ impl RpcService {
proposal_id: i32,
block_id: i64,
) -> Result<VersionedProposal, Status> {
let args = json!({ "proposal_id": proposal_id });
let args_encoded = general_purpose::STANDARD.encode(args.to_string().as_bytes());
let result = self
.query("get_proposal".to_string(), block_id, args_encoded)
.await;
let result: Result<Data<VersionedProposal>, near_api::errors::QueryError<RpcQueryRequest>> =
self.contract
.call_function("get_proposal", json!({ "proposal_id": proposal_id }))
.unwrap()
.read_only()
.at(Reference::AtBlock(block_id as u64))
.fetch_from(&self.network)
.await;

match result {
Ok(res) => {
// Deserialize the string as a Proposal type.
let proposal: VersionedProposal = serde_json::from_str(&res).unwrap();
println!("Deserialized proposal: {:?}", proposal);
Ok(proposal)
}
Ok(res) => Ok(res.data),
Err(e) => {
eprintln!("Failed to get proposal on block: {:?}", e);
Err(Status::InternalServerError)
Expand Down

0 comments on commit cf6384f

Please sign in to comment.