diff --git a/pallets/services/rpc/runtime-api/src/lib.rs b/pallets/services/rpc/runtime-api/src/lib.rs index 63e221283..ce528f843 100644 --- a/pallets/services/rpc/runtime-api/src/lib.rs +++ b/pallets/services/rpc/runtime-api/src/lib.rs @@ -21,7 +21,9 @@ use parity_scale_codec::Codec; use sp_runtime::{traits::MaybeDisplay, Serialize}; use sp_std::vec::Vec; -use tangle_primitives::services::{AssetIdT, Constraints, RpcServicesWithBlueprint}; +use tangle_primitives::services::{ + AssetIdT, Constraints, RpcServicesWithBlueprint, ServiceRequest, +}; pub type BlockNumberOf = <::HeaderT as sp_runtime::traits::Header>::Number; @@ -45,5 +47,18 @@ sp_api::decl_runtime_apis! { Vec, AssetId>>, sp_runtime::DispatchError, >; + + /// Query all pending service requests associated with a specific operator and blueprints. + /// + /// ## Arguments + /// - `operator`: The operator account id. + /// ## Return + /// - `Vec<(u64, ServiceRequest, AssetId>)>`: A list of service requests with their IDs. + fn query_service_requests_with_blueprints_by_operator( + operator: AccountId, + ) -> Result< + Vec<(u64, ServiceRequest, AssetId>)>, + sp_runtime::DispatchError, + >; } } diff --git a/pallets/services/rpc/src/lib.rs b/pallets/services/rpc/src/lib.rs index f5b749fb7..3e34fdc08 100644 --- a/pallets/services/rpc/src/lib.rs +++ b/pallets/services/rpc/src/lib.rs @@ -29,7 +29,9 @@ use sp_runtime::{ DispatchError, Serialize, }; use std::sync::Arc; -use tangle_primitives::services::{AssetIdT, Constraints, RpcServicesWithBlueprint}; +use tangle_primitives::services::{ + AssetIdT, Constraints, RpcServicesWithBlueprint, ServiceRequest, +}; type BlockNumberOf = <::HeaderT as sp_runtime::traits::Header>::Number; @@ -49,6 +51,13 @@ where operator: AccountId, at: Option, ) -> RpcResult>>; + + #[method(name = "services_queryServiceRequestsWithBlueprintsByOperator")] + fn query_service_requests_with_blueprints_by_operator( + &self, + operator: AccountId, + at: Option, + ) -> RpcResult)>>; } /// A struct that implements the `ServicesApi`. @@ -89,6 +98,21 @@ where Err(e) => Err(custom_error_into_rpc_err(Error::RuntimeError(e))), } } + + fn query_service_requests_with_blueprints_by_operator( + &self, + operator: AccountId, + at: Option<::Hash>, + ) -> RpcResult, AssetId>)>> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + match api.query_service_requests_with_blueprints_by_operator(at, operator) { + Ok(Ok(res)) => Ok(res), + Ok(Err(e)) => Err(custom_error_into_rpc_err(Error::CustomDispatchError(e))), + Err(e) => Err(custom_error_into_rpc_err(Error::RuntimeError(e))), + } + } } /// Error type of this RPC api. diff --git a/pallets/services/src/rpc.rs b/pallets/services/src/rpc.rs index 6950ff5cc..71c391f81 100644 --- a/pallets/services/src/rpc.rs +++ b/pallets/services/src/rpc.rs @@ -41,4 +41,38 @@ impl Pallet { } Ok(result) } + + #[allow(clippy::type_complexity)] + pub fn service_requests_with_blueprints_by_operator( + operator: T::AccountId, + ) -> Result< + Vec<(u64, ServiceRequest, T::AssetId>)>, + Error, + > { + // First we need to get the operator's profile to know which blueprints they're registered for + let profile = Self::operator_profile(&operator)?; + + // Get the operator's blueprints + let blueprint_ids = profile.blueprints; + + // Iterate through all service requests to find the ones for the operator's blueprints + // and where the operator is included in the requested operators + let mut result = Vec::new(); + + // We need to iterate through all service requests to check if operator is included + for (request_id, request) in ServiceRequests::::iter() { + // Check if the service request is for a blueprint the operator is registered for + if blueprint_ids.contains(&request.blueprint) { + // Check if the operator is one of the requested operators with approval state + if request.operators_with_approval_state.iter().any(|(op, _)| op == &operator) { + // Only include pending requests (those that haven't been approved by all operators yet) + if !request.is_approved() { + result.push((request_id, request)); + } + } + } + } + + Ok(result) + } } diff --git a/runtime/mainnet/src/lib.rs b/runtime/mainnet/src/lib.rs index 417f9a8d7..11dce839f 100644 --- a/runtime/mainnet/src/lib.rs +++ b/runtime/mainnet/src/lib.rs @@ -81,7 +81,7 @@ use sp_runtime::{ SaturatedConversion, }; use sp_staking::currency_to_vote::U128CurrencyToVote; -use tangle_primitives::services::RpcServicesWithBlueprint; +use tangle_primitives::services::{RpcServicesWithBlueprint, ServiceRequest}; pub use tangle_services::PalletServicesConstraints; #[cfg(any(feature = "std", test))] @@ -1963,6 +1963,15 @@ impl_runtime_apis! { > { Services::services_with_blueprints_by_operator(operator).map_err(Into::into) } + + fn query_service_requests_with_blueprints_by_operator( + operator: AccountId, + ) -> Result< + Vec<(u64, ServiceRequest, AssetId>)>, + sp_runtime::DispatchError, + > { + Services::service_requests_with_blueprints_by_operator(operator).map_err(Into::into) + } } impl pallet_rewards_rpc_runtime_api::RewardsApi for Runtime { diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 13af5e886..1f0e8cf81 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -95,7 +95,7 @@ use sp_std::{prelude::*, vec::Vec}; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use static_assertions::const_assert; -use tangle_primitives::services::RpcServicesWithBlueprint; +use tangle_primitives::services::{RpcServicesWithBlueprint, ServiceRequest}; pub use frame_support::{ construct_runtime, @@ -1653,6 +1653,15 @@ impl_runtime_apis! { > { Services::services_with_blueprints_by_operator(operator).map_err(Into::into) } + + fn query_service_requests_with_blueprints_by_operator( + operator: AccountId, + ) -> Result< + Vec<(u64, ServiceRequest, AssetId>)>, + sp_runtime::DispatchError, + > { + Services::service_requests_with_blueprints_by_operator(operator).map_err(Into::into) + } } impl pallet_rewards_rpc_runtime_api::RewardsApi for Runtime {