Skip to content

Commit

Permalink
feat: add service context for restaking delegations/metadata from ser…
Browse files Browse the repository at this point in the history
…vices
  • Loading branch information
drewstone committed Nov 16, 2024
1 parent 69e127b commit 3089d9f
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 69 deletions.
4 changes: 2 additions & 2 deletions blueprints/examples/src/eigen_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub async fn constructor(
get_provider_http(&env.http_rpc_endpoint),
);

Ok(FetchDetailsEventHandler::new(
Ok(HandleJobEventHandler::new(
example_task_manager,
ExampleEigenContext {
std_config: env.clone(),
Expand All @@ -59,7 +59,7 @@ pub async fn constructor(
pre_processor = handle_events,
),
)]
pub async fn fetch_details(
pub async fn handle_job(
ctx: ExampleEigenContext,
event: ExampleTaskManager::NewTaskCreated,
log: alloy_rpc_types::Log,
Expand Down
2 changes: 2 additions & 0 deletions blueprints/examples/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod eigen_context;
pub mod periodic_web_poller;
pub mod raw_tangle_events;
pub mod services_context;

#[cfg(test)]
mod tests;
3 changes: 2 additions & 1 deletion blueprints/examples/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use blueprint_examples::{eigen_context, periodic_web_poller, raw_tangle_events};
use blueprint_examples::{eigen_context, periodic_web_poller, raw_tangle_events, services_context};
use gadget_sdk::info;
use gadget_sdk::runners::eigenlayer::EigenlayerConfig;
use gadget_sdk::runners::{tangle::TangleConfig, BlueprintRunner};
Expand All @@ -19,6 +19,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
BlueprintRunner::new(TangleConfig::default(), env.clone())
.job(raw_tangle_events::constructor(env.clone()).await?)
.job(periodic_web_poller::constructor())
.job(services_context::constructor(env.clone()).await?)
.run()
.await?;
}
Expand Down
63 changes: 63 additions & 0 deletions blueprints/examples/src/services_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use gadget_sdk::ctx::TangleClientContext;
use gadget_sdk::event_listener::tangle::jobs::{services_post_processor, services_pre_processor};
use gadget_sdk::event_listener::tangle::TangleEventListener;
use gadget_sdk::event_utils::InitializableEventHandler;
use gadget_sdk::job;
use gadget_sdk::subxt_core::utils::AccountId32;
use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::services::events::JobCalled;
use gadget_sdk::{config::StdGadgetConfiguration, ctx::ServicesContext};

#[derive(Clone, ServicesContext, TangleClientContext)]
pub struct ExampleServiceContext {
#[config]
sdk_config: StdGadgetConfiguration,
}

pub async fn constructor(
env: StdGadgetConfiguration,
) -> color_eyre::Result<impl InitializableEventHandler> {
use gadget_sdk::subxt_core::tx::signer::Signer;

let signer = env
.clone()
.first_sr25519_signer()
.map_err(|e| color_eyre::eyre::eyre!(e))?;

gadget_sdk::info!("Starting the event watcher for {} ...", signer.account_id());
HandleJobEventHandler::new(&env.clone(), ExampleServiceContext { sdk_config: env })
.await
.map_err(|e| color_eyre::eyre::eyre!(e))
}

#[job(
id = 2,
params(job_details),
event_listener(
listener = TangleEventListener<ExampleServiceContext, JobCalled>,
pre_processor = services_pre_processor,
post_processor = services_post_processor
),
)]
pub async fn handle_job(
job_details: Vec<u8>,
context: ExampleServiceContext,
) -> Result<u64, gadget_sdk::Error> {
let client = context.tangle_client().await.unwrap();
let blueprint_owner = context.current_blueprint_owner(&client).await.unwrap();
let blueprint = context.current_blueprint(&client).await.unwrap();
let operators_and_percents = context.current_service_operators(&client).await.unwrap();
let operators = operators_and_percents
.iter()
.map(|(op, per)| op)
.cloned()
.collect::<Vec<AccountId32>>();
let restaking_delegations = context
.get_operator_delegations(&client, operators.clone())
.await
.unwrap();
let operators_metadata = context
.get_operators_metadata(&client, operators)
.await
.unwrap();
Ok(0)
}
156 changes: 100 additions & 56 deletions macros/context-derive/src/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,20 @@ pub fn generate_context_impl(
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::ServiceBlueprint,
gadget_sdk::ext::subxt::Error
>
> {
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
>{
use gadget_sdk::ext::subxt;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;

async move {
let blueprint_id = match #field_access.protocol_specific {
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => settings.blueprint_id,
_ => return Err(subxt::Error::Other("Blueprint id is only available for Tangle protocol".to_string())),
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => {
settings.blueprint_id
}
_ => {
return Err(subxt::Error::Other(
"Blueprint id is only available for Tangle protocol".to_string(),
))
}
};
let blueprint = api::storage().services().blueprints(blueprint_id);
let storage = client.storage().at_latest().await?;
Expand All @@ -55,13 +61,21 @@ pub fn generate_context_impl(
fn current_blueprint_owner(
&self,
client: &gadget_sdk::ext::subxt::OnlineClient<Self::Config>,
) -> impl core::future::Future<Output = Result<gadget_sdk::ext::subxt::utils::AccountId32, gadget_sdk::ext::subxt::Error>> {
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
) -> impl core::future::Future<
Output = Result<gadget_sdk::ext::subxt::utils::AccountId32, gadget_sdk::ext::subxt::Error>,
> {
use gadget_sdk::ext::subxt;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
async move {
let blueprint_id = match #field_access.protocol_specific {
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => settings.blueprint_id,
_ => return Err(subxt::Error::Other("Blueprint id is only available for Tangle protocol".to_string())),
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => {
settings.blueprint_id
}
_ => {
return Err(subxt::Error::Other(
"Blueprint id is only available for Tangle protocol".to_string(),
))
}
};
let blueprint = api::storage().services().blueprints(blueprint_id);
let storage = client.storage().at_latest().await?;
Expand All @@ -86,18 +100,28 @@ pub fn generate_context_impl(
)>,
gadget_sdk::ext::subxt::Error
>
> {
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
>{
use gadget_sdk::ext::subxt;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;

async move {
let service_instance_id = match #field_access.protocol_specific {
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => settings.service_id,
_ => return Err(subxt::Error::Other("Service instance id is only available for Tangle protocol".to_string())),
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => {
settings.service_id
}
_ => {
return Err(subxt::Error::Other(
"Service instance id is only available for Tangle protocol".to_string(),
))
}
};
let service_id = match service_instance_id {
Some(service_instance_id) => service_instance_id,
None => return Err(subxt::Error::Other("Service instance id is not set. Running in Registration mode?".to_string())),
Some(service_instance_id) => service_instance_id,
None => {
return Err(subxt::Error::Other(
"Service instance id is not set. Running in Registration mode?".to_string(),
))
}
};
let service_instance = api::storage().services().instances(service_id);
let storage = client.storage().at_latest().await?;
Expand All @@ -119,20 +143,25 @@ pub fn generate_context_impl(
Output = Result<
Vec<(
gadget_sdk::ext::subxt::utils::AccountId32,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::OperatorMetadata,
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::operator::OperatorMetadata<
gadget_sdk::ext::subxt::utils::AccountId32, // delegator
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::burned::Balance,
>,
)>,
gadget_sdk::ext::subxt::Error
>
> {
>{
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
use gadget_sdk::ext::subxt;

async move {
let storage = client.storage().at_latest().await?;
let mut operator_metadata = Vec::new();

for operator in operators {
let metadata_storage_key = api::storage().multi_asset_delegation().operators(operator.clone());
let metadata_storage_key = api::storage()
.multi_asset_delegation()
.operators(operator.clone());
let operator_metadata_result = storage.fetch(&metadata_storage_key).await?;
if let Some(metadata) = operator_metadata_result {
operator_metadata.push((operator, metadata));
Expand All @@ -148,11 +177,16 @@ pub fn generate_context_impl(
client: &gadget_sdk::ext::subxt::OnlineClient<Self::Config>,
operator: gadget_sdk::ext::subxt::utils::AccountId32,
) -> Result<
Option<gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::OperatorMetadata>,
Option<
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::operator::OperatorMetadata<
gadget_sdk::ext::subxt::utils::AccountId32, // delegator
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::burned::Balance,
>
>,
gadget_sdk::ext::subxt::Error,
> {
>{
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
use gadget_sdk::ext::subxt;

let storage = client.storage().at_latest().await?;
let metadata_storage_key = api::storage().multi_asset_delegation().operators(operator);
Expand All @@ -166,35 +200,35 @@ pub fn generate_context_impl(
) -> Result<
Vec<(
gadget_sdk::ext::subxt::utils::AccountId32, // operator
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::sp_std::collections::btree_map::BTreeMap<
gadget_sdk::ext::subxt::utils::AccountId32, // delegator
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::sp_std::collections::btree_map::BTreeMap<
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_assets::types::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_balances::types::Balance,
Option<
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::delegator::DelegatorMetadata<
gadget_sdk::ext::subxt::utils::AccountId32,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::burned::Balance,
>
>
)>,
gadget_sdk::ext::subxt::Error,
> {
>{
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
use gadget_sdk::ext::subxt;
use gadget_sdk::ext::subxt::utils::AccountId32;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::{
sp_std::collections::btree_map::BTreeMap,
pallet_assets::types::AssetId,
pallet_balances::types::Balance,
};
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::burned::Balance;
use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::delegator::DelegatorMetadata;

let storage = client.storage().at_latest().await?;
let mut operator_delegations: Vec<(AccountId32, BTreeMap<AccountId32, BTreeMap<AssetId, Balance>>)> = Vec::new();
let mut operator_delegations: Vec<(
AccountId32,
Option<DelegatorMetadata<AccountId32, AssetId, Balance>>,
)> = Vec::new();

for operator in operators {
let delegations_storage_key = api::storage().multi_asset_delegation().delegations_to(operator.clone());
let delegations_storage_key = api::storage()
.multi_asset_delegation()
.delegators(operator.clone());
let delegations_result = storage.fetch(&delegations_storage_key).await?;

if let Some(delegations) = delegations_result {
operator_delegations.push((operator, delegations.0));
}
operator_delegations.push((operator, delegations_result))
}

Ok(operator_delegations)
Expand All @@ -205,45 +239,55 @@ pub fn generate_context_impl(
client: &gadget_sdk::ext::subxt::OnlineClient<Self::Config>,
operator: gadget_sdk::ext::subxt::utils::AccountId32,
) -> Result<
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::sp_std::collections::btree_map::BTreeMap<
gadget_sdk::ext::subxt::utils::AccountId32, // delegator
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::sp_std::collections::btree_map::BTreeMap<
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_assets::types::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_balances::types::Balance,
Option<
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_multi_asset_delegation::types::delegator::DelegatorMetadata<
gadget_sdk::ext::subxt::utils::AccountId32,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::burned::Balance,
>
>,
gadget_sdk::ext::subxt::Error,
> {
>{
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
use gadget_sdk::ext::subxt;

let storage = client.storage().at_latest().await?;
let delegations_storage_key = api::storage().multi_asset_delegation().delegations_to(operator);
let delegations_storage_key = api::storage().multi_asset_delegation().delegators(operator);
let delegations_result = storage.fetch(&delegations_storage_key).await?;

match delegations_result {
Some(delegations) => Ok(delegations.0),
None => Ok(Default::default()),
}
Ok(delegations_result)
}

async fn get_service_instance(
&self,
client: &gadget_sdk::ext::subxt::OnlineClient<Self::Config>,
) -> Result<
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::runtime_types::pallet_services::types::Service,
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::Service<
gadget_sdk::ext::subxt::utils::AccountId32,
gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::system::storage::types::number::Number,
gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api::assets::events::force_created::AssetId,
>,
gadget_sdk::ext::subxt::Error,
> {
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;
>{
use gadget_sdk::ext::subxt;
use gadget_sdk::ext::tangle_subxt::tangle_testnet_runtime::api;

let service_instance_id = match &#field_access.protocol_specific {
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => settings.service_instance_id,
_ => return Err(subxt::Error::Other("Service instance id is only available for Tangle protocol".to_string())),
gadget_sdk::config::ProtocolSpecificSettings::Tangle(settings) => {
settings.service_id
}
_ => {
return Err(subxt::Error::Other(
"Service instance id is only available for Tangle protocol".to_string(),
))
}
};
let service_id = match service_instance_id {
Some(service_instance_id) => service_instance_id,
None => return Err(subxt::Error::Other("Service instance id is not set. Running in Registration mode?".to_string())),
None => {
return Err(subxt::Error::Other(
"Service instance id is not set. Running in Registration mode?".to_string(),
))
}
};
let service_instance = api::storage().services().instances(service_id);
let storage = client.storage().at_latest().await?;
Expand Down
Loading

0 comments on commit 3089d9f

Please sign in to comment.