From 327f7e2fc14392288aae86c8f0db9e50287fd4b4 Mon Sep 17 00:00:00 2001 From: Filip-L Date: Tue, 5 Aug 2025 18:03:43 +0200 Subject: [PATCH 1/2] Prepare backend to assing unallocated --- fplus-database/src/database/applications.rs | 17 +++ fplus-http-server/src/main.rs | 1 + fplus-http-server/src/router/application.rs | 22 ++- fplus-lib/src/core/application/allocation.rs | 13 ++ fplus-lib/src/core/application/file.rs | 14 +- fplus-lib/src/core/application/mod.rs | 11 ++ fplus-lib/src/core/mod.rs | 141 ++++++++++--------- 7 files changed, 149 insertions(+), 70 deletions(-) diff --git a/fplus-database/src/database/applications.rs b/fplus-database/src/database/applications.rs index 59731a9..7582b58 100644 --- a/fplus-database/src/database/applications.rs +++ b/fplus-database/src/database/applications.rs @@ -420,6 +420,23 @@ pub async fn get_applications_by_client_id( Ok(result) } +pub async fn get_applications_by_client_contract_address( + client_contract_address: &str, +) -> Result, sea_orm::DbErr> { + let conn = get_database_connection().await?; + let applications = Application::find() + .from_raw_sql(Statement::from_sql_and_values( + DbBackend::Postgres, + "SELECT DISTINCT ON (id) * FROM applications + WHERE client_contract_address = $1 + ORDER BY id, pr_number DESC", + [client_contract_address.into()], + )) + .all(&conn) + .await?; + Ok(applications) +} + pub async fn get_distinct_applications_by_clients_addresses( clients_addresses: Vec, ) -> Result, sea_orm::DbErr> { diff --git a/fplus-http-server/src/main.rs b/fplus-http-server/src/main.rs index a8cfb26..a2d49a8 100644 --- a/fplus-http-server/src/main.rs +++ b/fplus-http-server/src/main.rs @@ -99,6 +99,7 @@ async fn main() -> std::io::Result<()> { .service(router::application::closed_allocator_applications) .service(router::application::total_dc_reached) .service(router::application::single) + .service(router::application::get_applications_by_contract_address) .service(router::application::application_with_allocation_amount_handler) .service(router::application::validate_application_flow) .service(router::application::check_for_changes) diff --git a/fplus-http-server/src/router/application.rs b/fplus-http-server/src/router/application.rs index 73bc9ae..2c573ce 100644 --- a/fplus-http-server/src/router/application.rs +++ b/fplus-http-server/src/router/application.rs @@ -9,8 +9,9 @@ use fplus_lib::core::{ }, ApplicationQueryParams, BranchDeleteInfo, CompleteGovernanceReviewInfo, CompleteNewApplicationApprovalInfo, CompleteNewApplicationProposalInfo, CreateApplicationInfo, - DcReachedInfo, DecreaseAllowanceApprovalInfo, DecreaseAllowanceProposalInfo, GithubQueryParams, - LDNApplication, MoreInfoNeeded, NotifyRefillInfo, StorageProvidersChangeApprovalInfo, + DcReachedInfo, DecreaseAllowanceApprovalInfo, DecreaseAllowanceProposalInfo, + GetApplicationsByClientContractAddressQueryParams, GithubQueryParams, LDNApplication, + MoreInfoNeeded, NotifyRefillInfo, StorageProvidersChangeApprovalInfo, StorageProvidersChangeProposalInfo, SubmitKYCInfo, TriggerSSAInfo, ValidationPullRequestData, VerifierActionsQueryParams, }; @@ -50,6 +51,20 @@ pub async fn closed_applications() -> actix_web::Result { .body(parsed)) } +#[get("/applications/by_contract_address")] +pub async fn get_applications_by_contract_address( + query: web::Query, +) -> actix_web::Result { + let applications = + LDNApplication::get_applications_by_client_contract_address(&query.client_contract_address) + .await + .map_err(ErrorNotFound)?; + let parsed = serde_json::to_string_pretty(&applications).map_err(ErrorInternalServerError)?; + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(parsed)) +} + #[get("/applications/closed/allocator")] pub async fn closed_allocator_applications( query: web::Query, @@ -138,6 +153,7 @@ pub async fn propose( signer, request_id, new_allocation_amount, + amount_of_datacap_sent_to_contract, } = info.into_inner(); let ldn_application = LDNApplication::load(query.id.clone(), query.owner.clone(), query.repo.clone()) @@ -157,6 +173,7 @@ pub async fn propose( query.owner.clone(), query.repo.clone(), new_allocation_amount, + amount_of_datacap_sent_to_contract, ) .await .map_err(ErrorInternalServerError)?; @@ -315,6 +332,7 @@ pub async fn approve( query.owner.clone(), query.repo.clone(), None, + None, ) .await .map_err(ErrorInternalServerError)?; diff --git a/fplus-lib/src/core/application/allocation.rs b/fplus-lib/src/core/application/allocation.rs index 2e17be6..98f973b 100644 --- a/fplus-lib/src/core/application/allocation.rs +++ b/fplus-lib/src/core/application/allocation.rs @@ -26,6 +26,7 @@ impl AllocationRequest { kind, allocation_amount, is_active: true, + amount_of_datacap_sent_to_contract: None, } } } @@ -40,6 +41,7 @@ impl Allocation { is_active: true, amount: request_information.allocation_amount, signers: Verifiers::default(), + amount_of_datacap_sent_to_contract: None, } } @@ -108,6 +110,17 @@ impl Allocations { Self(res) } + pub fn set_amount_of_dc_sent_to_contract(&self, request_id: &str, amount: &str) -> Self { + let mut res: Vec = self.0.clone(); + for allocation in res.iter_mut() { + if allocation.id == request_id && allocation.is_active { + allocation.amount_of_datacap_sent_to_contract = Some(amount.into()); + break; + } + } + Self(res) + } + pub fn remove_signers_in_active_allocation(&mut self) -> Self { if let Some(alloc) = self.0.iter_mut().find(|alloc| alloc.is_active) { *alloc = alloc.remove_signers(); diff --git a/fplus-lib/src/core/application/file.rs b/fplus-lib/src/core/application/file.rs index d735c9c..208d936 100644 --- a/fplus-lib/src/core/application/file.rs +++ b/fplus-lib/src/core/application/file.rs @@ -339,6 +339,11 @@ pub struct Allocation { pub is_active: bool, #[serde(rename = "Allocation Amount")] pub amount: String, + #[serde( + rename = "Amount of Datacap Sent to Contract", + skip_serializing_if = "Option::is_none" + )] + pub amount_of_datacap_sent_to_contract: Option, #[serde(rename = "Signers")] pub signers: Verifiers, } @@ -436,7 +441,7 @@ pub struct VerifierInput { pub github_username: String, pub signing_address: String, pub created_at: String, - pub message_cid: String, + pub message_cid: Option, pub increase_allowance_cid: Option, } @@ -465,7 +470,7 @@ impl From<&DecreaseClientAllowanceVerifier> for Verifier { github_username: input.github_username.clone(), signing_address: input.signing_address.clone(), created_at: Utc::now().to_string(), - message_cid: input.decrease_allowance_cid.clone(), + message_cid: Some(input.decrease_allowance_cid.clone()), increase_allowance_cid: None, } } @@ -479,8 +484,8 @@ pub struct Verifier { pub signing_address: String, #[serde(rename = "Created At")] pub created_at: String, - #[serde(rename = "Message CID")] - pub message_cid: String, + #[serde(rename = "Message CID", skip_serializing_if = "Option::is_none")] + pub message_cid: Option, #[serde( rename = "Increase allowance CID", skip_serializing_if = "Option::is_none" @@ -518,6 +523,7 @@ pub struct AllocationRequest { pub kind: AllocationRequestType, pub is_active: bool, pub allocation_amount: String, + pub amount_of_datacap_sent_to_contract: Option, } #[derive(Serialize, Deserialize, Debug, Clone)] diff --git a/fplus-lib/src/core/application/mod.rs b/fplus-lib/src/core/application/mod.rs index 0625158..fc643b4 100644 --- a/fplus-lib/src/core/application/mod.rs +++ b/fplus-lib/src/core/application/mod.rs @@ -213,6 +213,17 @@ impl file::ApplicationFile { } } + pub fn set_amount_of_dc_sent_to_contract(&self, request_id: &str, amount: &str) -> Self { + let allocation_after_sign = self + .allocation + .clone() + .set_amount_of_dc_sent_to_contract(request_id, amount); + Self { + allocation: allocation_after_sign, + ..self.clone() + } + } + pub fn move_back_to_ready_to_sign(&self) -> Self { let updated_allocation = self .clone() diff --git a/fplus-lib/src/core/mod.rs b/fplus-lib/src/core/mod.rs index 859623f..87fdc8c 100644 --- a/fplus-lib/src/core/mod.rs +++ b/fplus-lib/src/core/mod.rs @@ -106,7 +106,7 @@ pub struct ApplicationProposalApprovalSignerInfo { #[derive(Serialize, Deserialize, Debug)] pub struct GrantDataCapCids { - pub message_cid: String, + pub message_cid: Option, pub increase_allowance_cid: Option, } @@ -115,6 +115,7 @@ pub struct CompleteNewApplicationProposalInfo { pub signer: ApplicationProposalApprovalSignerInfo, pub request_id: String, pub new_allocation_amount: Option, + pub amount_of_datacap_sent_to_contract: Option, } #[derive(Deserialize, Serialize, Debug)] @@ -258,6 +259,11 @@ pub struct ApplicationQueryParams { pub repo: String, } +#[derive(Deserialize)] +pub struct GetApplicationsByClientContractAddressQueryParams { + pub client_contract_address: String, +} + #[derive(Deserialize)] pub struct CompleteGovernanceReviewInfo { pub allocation_amount: String, @@ -573,6 +579,20 @@ impl LDNApplication { Ok(applications_response) } + pub async fn get_applications_by_client_contract_address( + client_contract_address: &str, + ) -> Result, LDNError> { + let applications = database::applications::get_applications_by_client_contract_address( + client_contract_address, + ) + .await + .map_err(|e| { + LDNError::Load(format!("Failed to get applications from the database: {e}")) + })?; + let applications_response = Self::prepare_applications_response(applications); + Ok(applications_response) + } + fn prepare_applications_response( applications: Vec, ) -> Vec { @@ -1150,6 +1170,7 @@ impl LDNApplication { owner: String, repo: String, new_allocation_amount: Option, + amount_of_datacap_sent_to_contract: Option, ) -> Result { // TODO: Convert DB errors to LDN Error // Get multisig threshold from the database @@ -1189,6 +1210,7 @@ impl LDNApplication { owner, repo, new_allocation_amount, + amount_of_datacap_sent_to_contract, ) .await; } @@ -1206,7 +1228,9 @@ impl LDNApplication { } app_file = app_file.update_lifecycle_after_sign_datacap_proposal(&signer.github_username); app_file = app_file.add_signer_to_allocation(signer.clone().into(), &request_id); - + if let Some(amount) = amount_of_datacap_sent_to_contract { + app_file = app_file.set_amount_of_dc_sent_to_contract(&request_id, &amount); + } if let Some(new_allocation_amount) = new_allocation_amount { if app_file.allocation.0.len() > 1 { let contract_address = db_allocator @@ -1280,7 +1304,7 @@ impl LDNApplication { Self::issue_datacap_request_signature( app_file.clone(), - "proposed".to_string(), + "Proposed".to_string(), owner.clone(), repo.clone(), ) @@ -1631,7 +1655,7 @@ impl LDNApplication { &request_id.to_string(), ); commit_message = LDNPullRequest::application_signed(&verifier.signing_address); - signature_step = "signed".to_string(); + signature_step = "Signed".to_string(); } else { app_file = app_file.add_signer_to_allocation_and_complete( verifier.into(), @@ -1640,7 +1664,7 @@ impl LDNApplication { ); commit_message = LDNPullRequest::application_move_to_confirmed_commit(&verifier.signing_address); - signature_step = "approved".to_string(); + signature_step = "Approved".to_string(); } self.update_and_commit_application_state( app_file.clone(), @@ -1694,6 +1718,7 @@ impl LDNApplication { owner: String, repo: String, new_allocation_amount: Option, + amount_of_datacap_sent_to_contract: Option, ) -> Result { // Get multisig threshold from the database let db_allocator = get_allocator(&owner, &repo) @@ -1759,7 +1784,7 @@ impl LDNApplication { ); commit_message = LDNPullRequest::application_move_to_confirmed_commit(&signer.signing_address); - signature_step = "approved".to_string(); + signature_step = "Approved".to_string(); comment = "Application is Granted"; label = AppState::Granted.as_str(); } else { @@ -1767,11 +1792,15 @@ impl LDNApplication { app_file.update_lifecycle_after_sign_datacap_proposal(&signer.github_username); app_file = app_file.add_signer_to_allocation(signer.clone().into(), &request_id); commit_message = LDNPullRequest::application_signed(&signer.signing_address); - signature_step = "signed".to_string(); + signature_step = "Signed".to_string(); comment = "Application is Granted"; label = AppState::StartSignDatacap.as_str(); } + if let Some(amount) = amount_of_datacap_sent_to_contract { + app_file = app_file.set_amount_of_dc_sent_to_contract(&request_id, &amount); + } + self.update_and_commit_application_state( app_file.clone(), self.github.owner.clone(), @@ -3716,78 +3745,62 @@ _(NEW vs OLD)_ Ok(true) } + fn filfox_link(cid: &str) -> String { + if !cid.is_empty() { + format!("- https://filfox.info/en/message/{cid}") + } else { + String::new() + } + } + async fn issue_datacap_request_signature( application_file: ApplicationFile, signature_step: String, owner: String, repo: String, - ) -> Result { - let active_allocation: Option<&Allocation> = - application_file.allocation.0.iter().find(|obj| { - Some(&obj.id) == application_file.lifecycle.active_request.clone().as_ref() - }); - - let signature_step_capitalized = signature_step - .chars() - .nth(0) - .ok_or(LDNError::Load("Failed to get signature step".to_string()))? - .to_uppercase() - .to_string() - + &signature_step.chars().skip(1).collect::(); - - let mut parsed_requested_datacap = String::new(); - let mut id = String::new(); - let mut signing_address = String::new(); - let mut message_cid = String::new(); - let mut increase_allowance_cid: Option = None; - - if let Some(allocation) = active_allocation { - parsed_requested_datacap = format_size_human_readable(&allocation.amount)?; - id.clone_from(&allocation.id); + ) -> Result<(), LDNError> { + let last_allocation = application_file + .get_last_request_allowance() + .ok_or(LDNError::Load("Last allocation not found".into()))?; + let last_sign_info = last_allocation + .signers + .0 + .last() + .ok_or(LDNError::Load("Failed to get last verifier".into()))?; + let signature_step_lowercase = signature_step.to_lowercase(); + let message_cid = last_sign_info.message_cid.clone().unwrap_or_default(); + let increase_allowance_cid = last_sign_info + .increase_allowance_cid + .clone() + .unwrap_or_default(); + let signing_address = last_sign_info.signing_address.clone(); + let client_address = application_file.id.clone(); + let parsed_requested_datacap = format_size_human_readable(&last_allocation.amount)?; + let request_id = last_allocation.id.clone(); + let increase_allowance_cid_filfox_link = Self::filfox_link(&increase_allowance_cid); - if let Some(first_verifier) = allocation.signers.0.last() { - signing_address.clone_from(&first_verifier.signing_address); - message_cid.clone_from(&first_verifier.message_cid); - increase_allowance_cid = first_verifier.increase_allowance_cid.clone(); - } - } - - let additional_status_message = - increase_allowance_cid - .clone() - .map_or("".to_string(), |increase_allowance_cid| { - format!(", and here https://filfox.info/en/message/{increase_allowance_cid}") - }); + let message_cid_filfox_link = Self::filfox_link(&message_cid); let comment = format!( - "## Request {} -Your Datacap Allocation Request has been {} by the Notary + "## Request {signature_step} +Your Datacap Allocation Request has been {signature_step_lowercase} by the Notary #### Message sent to Filecoin Network -> {} {} +> {message_cid} {increase_allowance_cid} #### Address -> {} +> {client_address} #### Datacap Allocated -> {} +> {parsed_requested_datacap} #### Signer Address -> {} +> {signing_address} #### Id -> {} -#### You can check the status here https://filfox.info/en/message/{}{}", - signature_step_capitalized, - signature_step, - message_cid, - increase_allowance_cid.unwrap_or_default(), - application_file.lifecycle.client_on_chain_address.clone(), - parsed_requested_datacap, - signing_address, - id, - message_cid, - additional_status_message +> {request_id} +#### You can check the status here: +{message_cid_filfox_link} +{increase_allowance_cid_filfox_link} +", ); - Self::add_comment_to_issue(application_file.issue_number, owner, repo, comment).await?; - - Ok(true) + Ok(()) } async fn issue_refill( From e64f6e55a04548c864bec54d4160504693f3a00c Mon Sep 17 00:00:00 2001 From: Filip-L Date: Mon, 11 Aug 2025 11:38:45 +0200 Subject: [PATCH 2/2] Change the comment published on GitHub --- fplus-lib/src/core/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fplus-lib/src/core/mod.rs b/fplus-lib/src/core/mod.rs index 87fdc8c..b1fcfb1 100644 --- a/fplus-lib/src/core/mod.rs +++ b/fplus-lib/src/core/mod.rs @@ -1583,7 +1583,7 @@ impl LDNApplication { app_file.issue_number.clone(), owner.to_string(), repo.to_string(), - format!("## Reason for not using Decreasing Allowance\n {reason_for_decrease}",), + format!("## Reason for using Decreasing Allowance\n {reason_for_decrease}",), ) .await?;