├── crates ├── contexts │ ├── src │ │ ├── p2p.rs │ │ ├── lib.rs │ │ ├── instrumented_evm_client.rs │ │ ├── services.rs │ │ ├── eigenlayer.rs │ │ ├── keystore.rs │ │ └── tangle.rs │ └── Cargo.toml ├── networking │ ├── src │ │ ├── setup.rs │ │ ├── tests │ │ │ └── mod.rs │ │ ├── lib.rs │ │ └── discovery │ │ │ └── mod.rs │ └── extensions │ │ └── agg-sig-gossip │ │ └── src │ │ └── lib.rs ├── runner │ └── src │ │ ├── symbiotic │ │ └── mod.rs │ │ ├── tangle │ │ ├── mod.rs │ │ └── error.rs │ │ └── eigenlayer │ │ ├── mod.rs │ │ └── error.rs ├── pricing-engine │ ├── src │ │ ├── benchmark │ │ │ └── types.rs │ │ └── service │ │ │ ├── rpc │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ └── blockchain │ │ │ └── mod.rs │ ├── build.rs │ └── operator.toml ├── core │ ├── src │ │ ├── ext_traits │ │ │ ├── mod.rs │ │ │ └── job │ │ │ │ └── mod.rs │ │ ├── extract │ │ │ ├── rejection.rs │ │ │ ├── from_ref.rs │ │ │ └── metadata.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ └── job │ │ │ └── future.rs │ ├── docs │ │ └── jobs_intro.md │ ├── Cargo.toml │ └── CHANGELOG.md ├── chain-setup │ ├── common │ │ ├── src │ │ │ └── lib.rs │ │ └── Cargo.toml │ ├── anvil │ │ ├── src │ │ │ ├── lib.rs │ │ │ ├── error.rs │ │ │ └── state.rs │ │ └── Cargo.toml │ ├── src │ │ └── lib.rs │ ├── tangle │ │ └── src │ │ │ └── error.rs │ └── Cargo.toml ├── manager │ ├── src │ │ ├── sdk │ │ │ ├── mod.rs │ │ │ └── entry.rs │ │ ├── rt │ │ │ ├── hypervisor │ │ │ │ └── assets │ │ │ │ │ ├── meta-data │ │ │ │ │ ├── network-config │ │ │ │ │ └── user-data │ │ │ ├── mod.rs │ │ │ └── native.rs │ │ ├── blueprint │ │ │ ├── mod.rs │ │ │ └── native.rs │ │ ├── protocol │ │ │ ├── tangle │ │ │ │ └── mod.rs │ │ │ └── eigenlayer │ │ │ │ └── mod.rs │ │ └── lib.rs │ └── bridge │ │ ├── src │ │ ├── api.rs │ │ ├── lib.rs │ │ └── error.rs │ │ ├── build.rs │ │ └── Cargo.toml ├── testing-utils │ ├── anvil │ │ ├── src │ │ │ ├── lib.rs │ │ │ └── anvil.rs │ │ └── Cargo.toml │ ├── eigenlayer │ │ ├── src │ │ │ └── lib.rs │ │ └── Cargo.toml │ ├── src │ │ └── lib.rs │ ├── tangle │ │ └── src │ │ │ ├── lib.rs │ │ │ └── keys.rs │ ├── Cargo.toml │ └── core │ │ ├── src │ │ ├── error.rs │ │ └── lib.rs │ │ └── Cargo.toml ├── macros │ ├── context-derive │ │ ├── src │ │ │ ├── tangle │ │ │ │ ├── mod.rs │ │ │ │ ├── client.rs │ │ │ │ └── services.rs │ │ │ └── keystore.rs │ │ ├── tests │ │ │ ├── ui │ │ │ │ ├── mod.rs │ │ │ │ ├── unit_struct.rs │ │ │ │ ├── not_a_struct.stderr │ │ │ │ ├── unit_struct.stderr │ │ │ │ ├── not_a_struct.rs │ │ │ │ ├── missing_config_attr.stderr │ │ │ │ ├── missing_config_attr.rs │ │ │ │ ├── unnamed_fields.rs │ │ │ │ └── generic_struct.rs │ │ │ └── tests.rs │ │ └── Cargo.toml │ ├── tests │ │ ├── debug_job │ │ │ ├── fail │ │ │ │ ├── not_a_function.rs │ │ │ │ ├── not_async.rs │ │ │ │ ├── generics.rs │ │ │ │ ├── invalid_attrs.rs │ │ │ │ ├── argument_not_extractor.rs │ │ │ │ ├── not_a_function.stderr │ │ │ │ ├── not_async.stderr │ │ │ │ ├── duplicate_args.rs │ │ │ │ ├── wrong_return_type.rs │ │ │ │ ├── invalid_attrs.stderr │ │ │ │ ├── not_send.rs │ │ │ │ ├── extract_self_ref.stderr │ │ │ │ ├── extract_self_mut.stderr │ │ │ │ ├── generics.stderr │ │ │ │ ├── duplicate_args.stderr │ │ │ │ ├── single_wrong_return_tuple.rs │ │ │ │ ├── extract_self_ref.rs │ │ │ │ ├── extract_self_mut.rs │ │ │ │ ├── wrong_return_type.stderr │ │ │ │ ├── not_send.stderr │ │ │ │ ├── single_wrong_return_tuple.stderr │ │ │ │ └── argument_not_extractor.stderr │ │ │ └── pass │ │ │ │ ├── ready.rs │ │ │ │ ├── associated_fn_without_self.rs │ │ │ │ ├── deny_unreachable_code.rs │ │ │ │ ├── impl_future.rs │ │ │ │ ├── impl_into_job_result.rs │ │ │ │ ├── set_ctx.rs │ │ │ │ ├── infer_context.rs │ │ │ │ └── self_receiver.rs │ │ └── from_ref │ │ │ ├── fail │ │ │ ├── generics.rs │ │ │ └── generics.stderr │ │ │ └── pass │ │ │ ├── reference-types.rs │ │ │ ├── skip.rs │ │ │ └── basic.rs │ ├── Cargo.toml │ └── src │ │ └── evm │ │ └── mod.rs ├── clients │ ├── eigenlayer │ │ └── src │ │ │ └── lib.rs │ ├── evm │ │ └── src │ │ │ ├── lib.rs │ │ │ ├── error.rs │ │ │ └── client.rs │ ├── src │ │ ├── lib.rs │ │ └── error.rs │ ├── core │ │ ├── Cargo.toml │ │ ├── src │ │ │ └── error.rs │ │ └── CHANGELOG.md │ ├── tangle │ │ ├── src │ │ │ └── lib.rs │ │ └── Cargo.toml │ └── Cargo.toml ├── auth │ ├── fixtures │ │ └── package.json │ ├── src │ │ └── tests │ │ │ └── mod.rs │ ├── build.rs │ └── proto │ │ └── grpc_proxy_test.proto ├── eigenlayer-extra │ ├── src │ │ ├── services │ │ │ └── mod.rs │ │ ├── sidecar │ │ │ └── mod.rs │ │ └── error.rs │ └── example-avs-config.json ├── metrics │ ├── src │ │ └── lib.rs │ ├── rpc-calls │ │ ├── Cargo.toml │ │ └── CHANGELOG.md │ ├── Cargo.toml │ └── CHANGELOG.md ├── qos │ ├── src │ │ ├── metrics │ │ │ ├── opentelemetry │ │ │ │ └── mod.rs │ │ │ ├── prometheus │ │ │ │ └── mod.rs │ │ │ └── provider │ │ │ │ └── mod.rs │ │ ├── logging │ │ │ └── mod.rs │ │ ├── metrics.rs │ │ ├── servers │ │ │ └── mod.rs │ │ └── error.rs │ ├── tests │ │ └── config │ │ │ └── prometheus.yml │ ├── build.rs │ ├── config │ │ ├── grafana_dashboard.json │ │ └── loki-config.yaml │ └── CHANGELOG.md ├── std │ ├── src │ │ ├── README.md │ │ └── error.rs │ ├── Cargo.toml │ └── CHANGELOG.md ├── tangle-extra │ └── src │ │ ├── metadata │ │ ├── types │ │ │ ├── mod.rs │ │ │ └── error.rs │ │ └── mod.rs │ │ ├── extract │ │ └── mod.rs │ │ ├── macros.rs │ │ ├── lib.rs │ │ └── filters.rs ├── stores │ ├── src │ │ ├── error.rs │ │ └── lib.rs │ ├── local-database │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ └── Cargo.toml ├── build-utils │ ├── Cargo.toml │ └── CHANGELOG.md ├── evm-extra │ └── src │ │ ├── extract │ │ ├── mod.rs │ │ └── tx.rs │ │ ├── lib.rs │ │ └── filters │ │ └── mod.rs ├── crypto │ ├── tangle-pair-signer │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ ├── bn254 │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ ├── bls │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ ├── sr25519 │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ ├── hashing │ │ ├── Cargo.toml │ │ ├── src │ │ │ └── lib.rs │ │ └── CHANGELOG.md │ ├── core │ │ └── Cargo.toml │ ├── k256 │ │ ├── src │ │ │ └── error.rs │ │ └── Cargo.toml │ └── ed25519 │ │ ├── Cargo.toml │ │ └── src │ │ └── error.rs ├── router │ ├── src │ │ ├── util.rs │ │ ├── test_helpers │ │ │ └── mod.rs │ │ └── tests.rs │ └── Cargo.toml ├── producers-extra │ ├── src │ │ └── lib.rs │ └── Cargo.toml ├── benchmarking │ ├── Cargo.toml │ └── CHANGELOG.md └── keystore │ ├── src │ └── lib.rs │ └── tests │ └── construction.rs ├── cli └── src │ ├── command │ ├── debug │ │ ├── mod.rs │ │ └── spawn │ │ │ ├── native.rs │ │ │ └── container.rs │ ├── list │ │ └── mod.rs │ ├── jobs │ │ └── mod.rs │ ├── deploy │ │ └── mod.rs │ ├── service │ │ └── mod.rs │ ├── run │ │ └── mod.rs │ ├── mod.rs │ ├── eigenlayer │ │ └── mod.rs │ └── create │ │ ├── error.rs │ │ ├── types.rs │ │ └── source.rs │ ├── tests │ ├── tangle │ │ └── mod.rs │ ├── eigenlayer │ │ └── mod.rs │ └── mod.rs │ ├── utils.rs │ ├── anvil │ └── error.rs │ └── foundry │ └── mod.rs ├── workspace-hack ├── src │ └── lib.rs ├── build.rs ├── .gitattributes └── Cargo.toml ├── clippy.toml ├── examples ├── incredible-squaring │ ├── remappings.txt │ ├── .config │ │ └── nextest.toml │ ├── soldeer.lock │ ├── .cargo │ │ └── config.toml │ ├── contracts │ │ └── src │ │ │ └── ExperimentalBlueprint.sol │ ├── package.json │ ├── tsconfig.json │ ├── .gitignore │ ├── incredible-squaring-bin │ │ ├── Cargo.toml │ │ └── build.rs │ ├── foundry.toml │ ├── incredible-squaring-lib │ │ ├── Cargo.toml │ │ ├── src │ │ │ └── lib.rs │ │ └── tests │ │ │ └── e2e.rs │ └── Cargo.toml ├── incredible-squaring-eigenlayer │ ├── src │ │ ├── jobs │ │ │ └── mod.rs │ │ ├── contexts │ │ │ ├── mod.rs │ │ │ ├── x_square.rs │ │ │ └── combined.rs │ │ └── error.rs │ ├── remappings.txt │ ├── contracts │ │ └── .gitignore │ ├── build.rs │ ├── .gitignore │ ├── soldeer.lock │ ├── settings.env │ ├── avs_contracts.json │ ├── foundry.toml │ └── core_contracts.json ├── apikey-blueprint │ ├── remappings.txt │ ├── Cargo.toml │ ├── soldeer.lock │ ├── foundry.toml │ ├── apikey-blueprint-bin │ │ ├── Cargo.toml │ │ └── build.rs │ └── apikey-blueprint-lib │ │ └── Cargo.toml └── oauth-blueprint │ ├── Cargo.toml │ ├── soldeer.lock │ ├── foundry.toml │ ├── oauth-blueprint-bin │ ├── Cargo.toml │ └── build.rs │ └── oauth-blueprint-lib │ └── Cargo.toml ├── taplo.toml ├── rustfmt.toml ├── rust-toolchain.toml ├── .cargo └── config.toml ├── .envrc ├── .editorconfig ├── .config ├── nextest.toml └── hakari.toml ├── .gitignore ├── .github ├── actions │ └── free-disk-space │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── build-setup.yml │ └── claude-review.yml ├── .dockerignore ├── docker-compose.yml ├── LICENSE-MIT └── dist-workspace.toml /crates/contexts/src/p2p.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /crates/networking/src/setup.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /crates/runner/src/symbiotic/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cli/src/command/debug/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod spawn; 2 | -------------------------------------------------------------------------------- /crates/pricing-engine/src/benchmark/types.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /crates/core/src/ext_traits/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod job; 2 | -------------------------------------------------------------------------------- /crates/chain-setup/common/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod signer; 2 | -------------------------------------------------------------------------------- /workspace-hack/src/lib.rs: -------------------------------------------------------------------------------- 1 | // This is a stub lib.rs. 2 | -------------------------------------------------------------------------------- /cli/src/tests/tangle/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod run; 2 | pub mod services; 3 | -------------------------------------------------------------------------------- /crates/manager/src/sdk/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod entry; 2 | pub mod utils; 3 | -------------------------------------------------------------------------------- /crates/pricing-engine/src/service/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod server; 2 | -------------------------------------------------------------------------------- /cli/src/command/list/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod blueprints; 2 | pub mod requests; 3 | -------------------------------------------------------------------------------- /cli/src/tests/eigenlayer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod deployment; 2 | pub mod run; 3 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | doc-valid-idents = ["EigenLayer", "UpperCamelCase", ".."] 2 | -------------------------------------------------------------------------------- /crates/runner/src/tangle/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod config; 2 | pub mod error; 3 | -------------------------------------------------------------------------------- /crates/pricing-engine/src/service/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod blockchain; 2 | pub mod rpc; 3 | -------------------------------------------------------------------------------- /crates/testing-utils/anvil/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod anvil; 2 | 3 | pub use anvil::*; 4 | -------------------------------------------------------------------------------- /cli/src/command/jobs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod check; 2 | pub mod helpers; 3 | pub mod submit; 4 | -------------------------------------------------------------------------------- /crates/macros/context-derive/src/tangle/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod services; 3 | -------------------------------------------------------------------------------- /cli/src/command/deploy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod eigenlayer; 2 | pub mod mbsm; 3 | pub mod tangle; 4 | -------------------------------------------------------------------------------- /cli/src/command/service/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod accept; 2 | pub mod reject; 3 | pub mod request; 4 | -------------------------------------------------------------------------------- /crates/manager/src/rt/hypervisor/assets/meta-data: -------------------------------------------------------------------------------- 1 | instance-id: {{BLUEPRINT_INSTANCE_ID}} 2 | -------------------------------------------------------------------------------- /examples/incredible-squaring/remappings.txt: -------------------------------------------------------------------------------- 1 | tnt-core/=dependencies/tnt-core-0.5.0/src 2 | -------------------------------------------------------------------------------- /cli/src/command/run/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod eigenlayer; 2 | pub use eigenlayer::*; 3 | pub mod tangle; 4 | -------------------------------------------------------------------------------- /cli/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod eigenlayer; 2 | pub mod keys; 3 | pub mod signers; 4 | pub mod tangle; 5 | -------------------------------------------------------------------------------- /crates/clients/eigenlayer/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod error; 3 | #[cfg(test)] 4 | mod tests; 5 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/mod.rs: -------------------------------------------------------------------------------- 1 | mod basic; 2 | mod generic_struct; 3 | mod unnamed_fields; 4 | -------------------------------------------------------------------------------- /taplo.toml: -------------------------------------------------------------------------------- 1 | [formatting] 2 | align_entries = false 3 | array_auto_expand = true 4 | column_width = 120 5 | -------------------------------------------------------------------------------- /crates/auth/fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@polkadot/keyring": "^13.5.1" 4 | } 5 | } -------------------------------------------------------------------------------- /crates/core/src/ext_traits/job/mod.rs: -------------------------------------------------------------------------------- 1 | mod call; 2 | pub use call::*; 3 | mod parts; 4 | pub use parts::*; 5 | -------------------------------------------------------------------------------- /crates/eigenlayer-extra/src/services/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod lifecycle; 2 | pub mod rewards; 3 | pub mod slashing; 4 | -------------------------------------------------------------------------------- /crates/metrics/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rpc-calls")] 2 | pub use blueprint_metrics_rpc_calls as rpc_calls; 3 | -------------------------------------------------------------------------------- /crates/runner/src/eigenlayer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bls; 2 | pub mod config; 3 | pub mod ecdsa; 4 | pub mod error; 5 | -------------------------------------------------------------------------------- /crates/networking/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | mod blueprint_protocol; 2 | mod discovery; 3 | mod gossip; 4 | mod handshake; 5 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/src/jobs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod compute_x_square; 2 | pub mod initialize_task; 3 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | format_code_in_doc_comments = true 2 | format_macro_bodies = true 3 | format_macro_matchers = true 4 | -------------------------------------------------------------------------------- /workspace-hack/build.rs: -------------------------------------------------------------------------------- 1 | // A build script is required for cargo to consider build dependencies. 2 | fn main() {} 3 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/remappings.txt: -------------------------------------------------------------------------------- 1 | tnt-core/=dependencies/tnt-core-0.5.0/ 2 | tnt-core/=dependencies/tnt-core/src/ 3 | -------------------------------------------------------------------------------- /crates/manager/bridge/src/api.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::all, clippy::pedantic)] 2 | 3 | tonic::include_proto!("blueprint_manager_bridge"); 4 | -------------------------------------------------------------------------------- /crates/qos/src/metrics/opentelemetry/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod exporter; 2 | 3 | pub use exporter::{OpenTelemetryConfig, OpenTelemetryExporter}; 4 | -------------------------------------------------------------------------------- /crates/eigenlayer-extra/src/sidecar/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod types; 3 | 4 | pub use client::SidecarClient; 5 | pub use types::*; 6 | -------------------------------------------------------------------------------- /crates/std/src/README.md: -------------------------------------------------------------------------------- 1 | # std 2 | 3 | The Blueprint std library is used to provide std / no_std features for the Blueprint ecosystem. 4 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_a_function.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | struct A; 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_async.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | fn handler() {} 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/metadata/types/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod blueprint; 2 | pub mod error; 3 | pub mod job; 4 | pub mod report; 5 | pub mod sources; 6 | -------------------------------------------------------------------------------- /crates/clients/evm/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | pub mod client; 4 | pub mod error; 5 | pub mod instrumented_client; 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/generics.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | async fn job(_extract: T) {} 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/invalid_attrs.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job(foo)] 4 | async fn job() {} 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/argument_not_extractor.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | async fn job(_foo: bool) {} 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/pricing-engine/src/service/blockchain/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod event; 2 | pub mod listener; 3 | 4 | pub use event::BlockchainEvent; 5 | pub use listener::EventListener; 6 | -------------------------------------------------------------------------------- /crates/qos/src/metrics/prometheus/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod collector; 2 | pub mod server; 3 | 4 | pub use collector::PrometheusCollector; 5 | pub use server::PrometheusServer; 6 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/src/contexts/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregator; 2 | pub mod client; 3 | pub mod combined; 4 | pub mod eigen_task; 5 | pub mod x_square; 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_a_function.stderr: -------------------------------------------------------------------------------- 1 | error: expected `fn` 2 | --> tests/debug_job/fail/not_a_function.rs:4:1 3 | | 4 | 4 | struct A; 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_async.stderr: -------------------------------------------------------------------------------- 1 | error: Jobs must be `async fn`s 2 | --> tests/debug_job/fail/not_async.rs:4:1 3 | | 4 | 4 | fn handler() {} 5 | | ^^ 6 | -------------------------------------------------------------------------------- /crates/qos/src/metrics/provider/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod default; 2 | pub mod enhanced; 3 | 4 | pub use default::DefaultMetricsProvider; 5 | pub use enhanced::EnhancedMetricsProvider; 6 | -------------------------------------------------------------------------------- /crates/testing-utils/eigenlayer/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod env; 2 | pub mod harness; 3 | pub mod runner; 4 | 5 | pub use blueprint_core_testing_utils::Error; 6 | pub use harness::*; 7 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/unit_struct.rs: -------------------------------------------------------------------------------- 1 | use blueprint_context_derive::KeystoreContext; 2 | 3 | #[derive(KeystoreContext)] 4 | struct MyContext; 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/duplicate_args.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job(context = (), context = ())] 4 | async fn job() {} 5 | 6 | fn main() {} 7 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/wrong_return_type.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | async fn job() -> bool { 5 | false 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /examples/incredible-squaring/.config/nextest.toml: -------------------------------------------------------------------------------- 1 | [profile.ci] 2 | failure-output = "immediate-final" 3 | fail-fast = false 4 | slow-timeout = { period = "240s", terminate-after = 4 } 5 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.88" # Update the workspace rust-version as well 3 | components = ["cargo", "rustfmt", "clippy", "rust-src"] 4 | profile = "minimal" 5 | -------------------------------------------------------------------------------- /crates/macros/tests/from_ref/fail/generics.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::extract::FromRef; 2 | 3 | #[derive(Clone, FromRef)] 4 | struct AppContext { 5 | foo: T, 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/invalid_attrs.stderr: -------------------------------------------------------------------------------- 1 | error: expected `context` 2 | --> tests/debug_job/fail/invalid_attrs.rs:3:13 3 | | 4 | 3 | #[debug_job(foo)] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "3" 3 | members = [ 4 | "apikey-blueprint-lib", 5 | "apikey-blueprint-bin", 6 | ] 7 | 8 | [workspace.package] 9 | edition = "2024" -------------------------------------------------------------------------------- /examples/oauth-blueprint/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "3" 3 | members = [ 4 | "oauth-blueprint-lib", 5 | "oauth-blueprint-bin", 6 | ] 7 | 8 | [workspace.package] 9 | edition = "2024" -------------------------------------------------------------------------------- /crates/manager/src/blueprint/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::rt::service::Service; 2 | use blueprint_std::collections::HashMap; 3 | 4 | pub type ActiveBlueprints = HashMap>; 5 | pub mod native; 6 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/soldeer.lock: -------------------------------------------------------------------------------- 1 | [[dependencies]] 2 | name = "tnt-core" 3 | version = "0.5.0" 4 | git = "https://github.com/tangle-network/tnt-core" 5 | rev = "a27aa6158f0c7436a68923fa1478668275d05c5c" 6 | -------------------------------------------------------------------------------- /examples/oauth-blueprint/soldeer.lock: -------------------------------------------------------------------------------- 1 | [[dependencies]] 2 | name = "tnt-core" 3 | version = "0.5.0" 4 | git = "https://github.com/tangle-network/tnt-core" 5 | rev = "a27aa6158f0c7436a68923fa1478668275d05c5c" 6 | -------------------------------------------------------------------------------- /crates/chain-setup/anvil/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod anvil; 2 | pub mod error; 3 | pub mod keys; 4 | pub mod state; 5 | 6 | pub use anvil::*; 7 | 8 | pub use state::{AnvilState, get_default_state, get_default_state_json}; 9 | -------------------------------------------------------------------------------- /examples/incredible-squaring/soldeer.lock: -------------------------------------------------------------------------------- 1 | [[dependencies]] 2 | name = "tnt-core" 3 | version = "0.5.0" 4 | git = "https://github.com/tangle-network/tnt-core" 5 | rev = "a27aa6158f0c7436a68923fa1478668275d05c5c" 6 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/not_a_struct.stderr: -------------------------------------------------------------------------------- 1 | error: Context Extensions traits can only be derived for structs 2 | --> tests/ui/not_a_struct.rs:4:6 3 | | 4 | 4 | enum MyContext { 5 | | ^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/ready.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use std::future::{Ready, ready}; 3 | 4 | #[debug_job] 5 | fn job() -> Ready<()> { 6 | ready(()) 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /crates/macros/tests/from_ref/fail/generics.stderr: -------------------------------------------------------------------------------- 1 | error: `#[derive(FromRef)]` doesn't support generics 2 | --> tests/from_ref/fail/generics.rs:4:18 3 | | 4 | 4 | struct AppContext { 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /crates/qos/src/logging/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod grafana; 2 | pub mod loki; 3 | 4 | pub use self::grafana::{GrafanaClient, GrafanaConfig}; 5 | pub use self::loki::{LokiConfig, OtelConfig, init_loki_logging, init_otel_tracer}; 6 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/unit_struct.stderr: -------------------------------------------------------------------------------- 1 | error: Context Extensions traits cannot be derived for unit structs 2 | --> tests/ui/unit_struct.rs:4:8 3 | | 4 | 4 | struct MyContext; 5 | | ^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_send.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | #[debug_job] 4 | async fn job() { 5 | let _rc = std::rc::Rc::new(()); 6 | async {}.await; 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/associated_fn_without_self.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | 3 | struct A; 4 | 5 | impl A { 6 | #[debug_job] 7 | async fn job() {} 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/deny_unreachable_code.rs: -------------------------------------------------------------------------------- 1 | #![deny(unreachable_code)] 2 | 3 | use blueprint_sdk::JobCall; 4 | 5 | #[blueprint_macros::debug_job] 6 | async fn job(_call: JobCall) {} 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /crates/qos/src/metrics.rs: -------------------------------------------------------------------------------- 1 | pub mod opentelemetry; 2 | pub mod prometheus; 3 | pub mod provider; 4 | pub mod service; 5 | pub mod types; 6 | 7 | pub use provider::*; 8 | pub use service::*; 9 | pub use types::*; 10 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-apple-darwin] 2 | linker = "clang++" 3 | 4 | [env] 5 | CXXFLAGS = "-include cstdint" 6 | 7 | [build] 8 | # For access to tokio metrics 9 | rustflags = ["--cfg", "tokio_unstable"] 10 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/not_a_struct.rs: -------------------------------------------------------------------------------- 1 | use blueprint_context_derive::KeystoreContext; 2 | 3 | #[derive(KeystoreContext)] 4 | enum MyContext { 5 | Variant1, 6 | Variant2, 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/extract_self_ref.stderr: -------------------------------------------------------------------------------- 1 | error: Jobs must only take owned values 2 | --> tests/debug_job/fail/extract_self_ref.rs:19:18 3 | | 4 | 19 | async fn job(&self) {} 5 | | ^^^^^ 6 | -------------------------------------------------------------------------------- /crates/pricing-engine/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | println!("cargo:rerun-if-changed=proto/pricing.proto"); 3 | tonic_build::compile_protos("proto/pricing.proto")?; 4 | Ok(()) 5 | } 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/impl_future.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use core::future::Future; 3 | 4 | #[debug_job] 5 | fn handler() -> impl Future { 6 | async {} 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /crates/macros/tests/from_ref/pass/reference-types.rs: -------------------------------------------------------------------------------- 1 | #![deny(noop_method_call)] 2 | 3 | use blueprint_macros::FromRef; 4 | 5 | #[derive(FromRef)] 6 | struct MyContext { 7 | inner: &'static str, 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/remappings.txt: -------------------------------------------------------------------------------- 1 | @openzeppelin-contracts/=dependencies/@openzeppelin-contracts-4.7.0/ 2 | eigenlayer-middleware/=dependencies/eigenlayer-middleware-1.3.1/ 3 | forge-std/=dependencies/forge-std-1.9.6/ 4 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/extract_self_mut.stderr: -------------------------------------------------------------------------------- 1 | error: Jobs must only take owned values 2 | --> tests/debug_job/fail/extract_self_mut.rs:19:18 3 | | 4 | 19 | async fn job(&mut self) {} 5 | | ^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/generics.stderr: -------------------------------------------------------------------------------- 1 | error: `#[blueprint_macros::debug_job]` doesn't support generic functions 2 | --> tests/debug_job/fail/generics.rs:4:13 3 | | 4 | 4 | async fn job(_extract: T) {} 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /cli/src/command/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod create; 2 | pub mod debug; 3 | pub mod deploy; 4 | pub mod eigenlayer; 5 | pub mod jobs; 6 | pub mod keys; 7 | pub mod list; 8 | pub mod register; 9 | pub mod run; 10 | pub mod service; 11 | pub mod signer; 12 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/impl_into_job_result.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::IntoJobResult; 3 | 4 | #[debug_job] 5 | async fn job() -> impl IntoJobResult { 6 | "hi!" 7 | } 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /crates/chain-setup/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "anvil")] 2 | pub use blueprint_chain_setup_anvil as anvil; 3 | 4 | #[cfg(feature = "tangle")] 5 | pub use blueprint_chain_setup_tangle as tangle; 6 | 7 | pub use blueprint_chain_setup_common as common; 8 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/duplicate_args.stderr: -------------------------------------------------------------------------------- 1 | error: `context` specified more than once 2 | --> tests/debug_job/fail/duplicate_args.rs:3:27 3 | | 4 | 3 | #[debug_job(context = (), context = ())] 5 | | ^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/macros/tests/from_ref/pass/skip.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::FromRef; 2 | 3 | #[derive(Clone, FromRef)] 4 | struct MyContext { 5 | auth_token: String, 6 | #[from_ref(skip)] 7 | also_string: String, 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /workspace-hack/.gitattributes: -------------------------------------------------------------------------------- 1 | # Avoid putting conflict markers in the generated Cargo.toml file, since their presence breaks 2 | # Cargo. 3 | # Also do not check out the file as CRLF on Windows, as that's what hakari needs. 4 | Cargo.toml merge=binary -crlf 5 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/single_wrong_return_tuple.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_parens)] 2 | 3 | struct NotIntoJobResult; 4 | 5 | #[blueprint_macros::debug_job] 6 | async fn job() -> (NotIntoJobResult) { 7 | panic!() 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /crates/chain-setup/tangle/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::io; 2 | 3 | #[derive(Debug)] 4 | pub enum Error { 5 | Io(io::Error), 6 | CouldNotExtractPort(String), 7 | CouldNotExtractP2pAddress(String), 8 | CouldNotExtractP2pPort(String), 9 | } 10 | -------------------------------------------------------------------------------- /crates/auth/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod advanced_tests; 2 | pub mod api_key_lifecycle_tests; 3 | pub mod grpc_proxy_tests; 4 | pub mod mtls_flow_tests; 5 | pub mod multi_tenancy_tests; 6 | pub mod oauth_tests; 7 | pub mod security_isolation_tests; 8 | pub mod token_exchange_tests; 9 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" 3 | fi 4 | use flake 5 | watch_file flake.nix 6 | # vi: ft=sh 7 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/contracts/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiler files 2 | cache/ 3 | out/ 4 | 5 | # Ignores development broadcast logs 6 | !/broadcast 7 | /broadcast/*/31337/ 8 | /broadcast/**/dry-run/ 9 | 10 | # Docs 11 | docs/ 12 | 13 | # Dotenv file 14 | .env 15 | -------------------------------------------------------------------------------- /crates/manager/bridge/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | tonic_build::configure() 3 | .protoc_arg("--experimental_allow_proto3_optional") 4 | .build_server(true) 5 | .compile_protos(&["proto/bridge.proto"], &["proto"])?; 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /crates/manager/bridge/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod error; 2 | pub use error::Error; 3 | 4 | mod api; 5 | pub use api::*; 6 | 7 | mod tls_profile; 8 | 9 | pub const VSOCK_PORT: u32 = 8000; 10 | 11 | #[cfg(feature = "client")] 12 | pub mod client; 13 | #[cfg(feature = "server")] 14 | pub mod server; 15 | -------------------------------------------------------------------------------- /crates/manager/src/rt/hypervisor/assets/network-config: -------------------------------------------------------------------------------- 1 | network: 2 | version: 2 3 | ethernets: 4 | ens5: 5 | dhcp4: false 6 | addresses: 7 | - {{GUEST_IP_ADDRESS}}/24 8 | gateway4: {{TAP_IP_ADDRESS}} 9 | nameservers: 10 | addresses: [1.1.1.1, 8.8.8.8] 11 | -------------------------------------------------------------------------------- /examples/incredible-squaring/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | CXXFLAGS = "-include cstdint" 3 | 4 | # Temporary hack for Tangle blueprints to get the workspace root 5 | # 6 | # See: https://github.com/rust-lang/cargo/issues/3946#issuecomment-973132993 7 | CARGO_WORKSPACE_DIR = { value = "", relative = true } 8 | -------------------------------------------------------------------------------- /crates/contexts/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "eigenlayer")] 2 | pub mod eigenlayer; 3 | #[cfg(feature = "evm")] 4 | pub mod instrumented_evm_client; 5 | #[cfg(feature = "keystore")] 6 | pub mod keystore; 7 | #[cfg(feature = "tangle")] 8 | pub mod services; 9 | #[cfg(feature = "tangle")] 10 | pub mod tangle; 11 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/missing_config_attr.stderr: -------------------------------------------------------------------------------- 1 | error: No field with #[config] attribute found, please add #[config] to the field that holds the `blueprint_runner::config::BlueprintEnvironment` 2 | --> tests/ui/missing_config_attr.rs:5:8 3 | | 4 | 5 | struct MyContext { 5 | | ^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [.github/workflows/*.{yaml,yml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/missing_config_attr.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::runner::config::BlueprintEnvironment; 2 | use blueprint_context_derive::KeystoreContext; 3 | 4 | #[derive(KeystoreContext)] 5 | struct MyContext { 6 | foo: String, 7 | sdk_config: BlueprintEnvironment, 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /.config/nextest.toml: -------------------------------------------------------------------------------- 1 | [profile.ci] 2 | failure-output = "immediate-final" 3 | fail-fast = false 4 | slow-timeout = { period = "300s", terminate-after = 4 } 5 | 6 | [profile.serial] 7 | test-threads = 1 8 | failure-output = "immediate-final" 9 | fail-fast = false 10 | slow-timeout = { period = "300s", terminate-after = 4 } 11 | -------------------------------------------------------------------------------- /crates/contexts/src/instrumented_evm_client.rs: -------------------------------------------------------------------------------- 1 | pub use blueprint_clients::evm::instrumented_client::InstrumentedClient; 2 | 3 | /// `EvmInstrumentedClientContext` trait provides access to the EVM provider from the context. 4 | pub trait EvmInstrumentedClientContext { 5 | async fn evm_client(&self) -> InstrumentedClient; 6 | } 7 | -------------------------------------------------------------------------------- /crates/auth/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Generate test gRPC service definitions for integration tests. 3 | tonic_build::configure() 4 | .build_client(true) 5 | .build_server(true) 6 | .compile_protos(&["proto/grpc_proxy_test.proto"], &["proto"]) 7 | .expect("failed to build gRPC test protos"); 8 | } 9 | -------------------------------------------------------------------------------- /crates/manager/bridge/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, thiserror::Error)] 2 | pub enum Error { 3 | #[error(transparent)] 4 | Io(#[from] std::io::Error), 5 | 6 | #[error(transparent)] 7 | Transport(#[from] tonic::transport::Error), 8 | 9 | #[error(transparent)] 10 | Status(#[from] tonic::Status), 11 | } 12 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let contract_dirs: Vec<&str> = vec!["./contracts"]; 3 | println!("cargo::rerun-if-changed=./contracts/src"); 4 | 5 | blueprint_build_utils::soldeer_install(); 6 | blueprint_build_utils::soldeer_update(); 7 | blueprint_build_utils::build_contracts(contract_dirs); 8 | } 9 | -------------------------------------------------------------------------------- /crates/testing-utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use blueprint_core_testing_utils::*; 2 | 3 | #[cfg(feature = "anvil")] 4 | pub use blueprint_anvil_testing_utils as anvil; 5 | 6 | #[cfg(feature = "tangle")] 7 | pub use blueprint_tangle_testing_utils as tangle; 8 | 9 | #[cfg(feature = "eigenlayer")] 10 | pub use blueprint_eigenlayer_testing_utils as eigenlayer; 11 | -------------------------------------------------------------------------------- /crates/manager/src/protocol/tangle/mod.rs: -------------------------------------------------------------------------------- 1 | /// Tangle Protocol implementation for blueprint manager 2 | /// 3 | /// This module contains the Tangle-specific client and event handler. 4 | pub mod client; 5 | pub mod event_handler; 6 | 7 | #[cfg(test)] 8 | mod tests; 9 | 10 | pub use client::TangleProtocolClient; 11 | pub use event_handler::TangleEventHandler; 12 | -------------------------------------------------------------------------------- /crates/qos/tests/config/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 10s 3 | evaluation_interval: 10s 4 | 5 | scrape_configs: 6 | - job_name: 'prometheus' 7 | static_configs: 8 | - targets: ['localhost:9090'] 9 | 10 | - job_name: 'blueprint_test_app_metrics' 11 | metrics_path: /metrics 12 | static_configs: 13 | - targets: ['host.docker.internal:9091'] 14 | -------------------------------------------------------------------------------- /crates/auth/proto/grpc_proxy_test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package blueprint.auth.grpcproxytest; 4 | 5 | service EchoService { 6 | rpc Echo(EchoRequest) returns (EchoResponse); 7 | rpc EchoStream(stream EchoRequest) returns (stream EchoResponse); 8 | } 9 | 10 | message EchoRequest { 11 | string message = 1; 12 | } 13 | 14 | message EchoResponse { 15 | string message = 1; 16 | } 17 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/metadata/types/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error("The blueprint.json defines no sources. There must be at least 1")] 4 | NoSources, 5 | #[error("Encountered a malformed source in the blueprint.json")] 6 | BadSource, 7 | 8 | #[error("Failed to parse the blueprint service manager")] 9 | BadServiceManager, 10 | } 11 | -------------------------------------------------------------------------------- /crates/clients/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | pub mod error; 4 | pub use error::*; 5 | 6 | #[cfg(feature = "eigenlayer")] 7 | pub use blueprint_client_eigenlayer as eigenlayer; 8 | 9 | #[cfg(feature = "evm")] 10 | pub use blueprint_client_evm as evm; 11 | 12 | #[cfg(feature = "tangle")] 13 | pub use blueprint_client_tangle as tangle; 14 | 15 | pub use blueprint_client_core::*; 16 | -------------------------------------------------------------------------------- /crates/contexts/src/services.rs: -------------------------------------------------------------------------------- 1 | pub use blueprint_clients::tangle::services::TangleServicesClient; 2 | 3 | /// `ServicesContext` trait provides access to the Services client from the context. 4 | pub trait ServicesContext { 5 | /// Returns the Services client instance 6 | async fn services_client( 7 | &self, 8 | ) -> TangleServicesClient; 9 | } 10 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/src/contexts/x_square.rs: -------------------------------------------------------------------------------- 1 | use crate::contexts::client::AggregatorClient; 2 | use blueprint_sdk::macros::context::KeystoreContext; 3 | use blueprint_sdk::runner::config::BlueprintEnvironment; 4 | 5 | #[derive(Clone, KeystoreContext)] 6 | pub struct EigenSquareContext { 7 | pub client: AggregatorClient, 8 | #[config] 9 | pub std_config: BlueprintEnvironment, 10 | } 11 | -------------------------------------------------------------------------------- /cli/src/command/eigenlayer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod deregister; 2 | pub mod list; 3 | /// EigenLayer AVS registration management commands 4 | pub mod register; 5 | pub mod rewards; 6 | pub mod sync; 7 | 8 | pub use deregister::deregister_avs; 9 | pub use list::list_avs_registrations; 10 | pub use register::register_avs; 11 | pub use rewards::{claim_rewards, set_claimer, show_rewards}; 12 | pub use sync::sync_avs_registrations; 13 | -------------------------------------------------------------------------------- /crates/qos/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | tonic_build::configure() 3 | .protoc_arg("--experimental_allow_proto3_optional") 4 | .build_server(true) 5 | .type_attribute(".", "#[allow(clippy::pedantic, clippy::missing_errors_doc, clippy::derive_partial_eq_without_eq, clippy::must_use_candidate)]") 6 | .compile_protos(&["proto/qos.proto"], &["proto"])?; 7 | Ok(()) 8 | } 9 | -------------------------------------------------------------------------------- /crates/stores/src/error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can occur within blueprint storage providers 2 | #[derive(thiserror::Error, Debug)] 3 | pub enum Error { 4 | /// Errors from the [`LocalDatabase`] 5 | /// 6 | /// [`LocalDatabase`]: blueprint_store_local_database::LocalDatabase 7 | #[cfg(feature = "local")] 8 | #[error("Local database error: {0}")] 9 | LocalDatabase(#[from] blueprint_store_local_database::Error), 10 | } 11 | -------------------------------------------------------------------------------- /crates/core/docs/jobs_intro.md: -------------------------------------------------------------------------------- 1 | In the Blueprint SDK a "job" is an async function that accepts zero or more 2 | ["extractors"](crate::extract) as arguments and returns something that 3 | can be converted [into a job result](crate::job::result). 4 | 5 | Jobs are where your application logic lives, and Blueprints are built by routing between one or many of them. 6 | 7 | [`debug_job`]: https://docs.rs/blueprint-macros/latest/blueprint_macros/attr.debug_job.html 8 | -------------------------------------------------------------------------------- /crates/build-utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-build-utils" 3 | version = "0.1.0-alpha.4" 4 | description = "Tangle Blueprint build utils" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-std = { workspace = true, features = ["std"] } 17 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/metadata/mod.rs: -------------------------------------------------------------------------------- 1 | /// Job Definitions and Metadata 2 | mod job_definition; 3 | #[cfg(feature = "macros")] 4 | pub mod macros; 5 | /// Service Definition and Metadata 6 | mod service; 7 | /// Types used in the generation of the `blueprint.json` file 8 | #[cfg(feature = "metadata-types")] 9 | pub mod types; 10 | 11 | pub use job_definition::{IntoJobDefinition, IntoJobMetadata, IntoTangleFieldTypes}; 12 | pub use service::IntoServiceMetadata; 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # These are backup files generated by rustfmt 2 | **/*.rs.bk 3 | 4 | # MSVC Windows builds of rustc generate these, which store debugging information 5 | *.pdb 6 | 7 | # Added by cargo 8 | /target 9 | .idea 10 | .vscode 11 | 12 | .direnv 13 | certs 14 | .DS_Store 15 | db 16 | 17 | node_modules 18 | 19 | **/contracts/out/ 20 | **/contracts/cache/ 21 | **/dependencies/ 22 | 23 | blueprint.lock 24 | blueprint.json 25 | cache 26 | target 27 | 28 | .cursor/ 29 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/extract/mod.rs: -------------------------------------------------------------------------------- 1 | mod call_id; 2 | pub use call_id::*; 3 | mod args; 4 | pub use args::*; 5 | mod result; 6 | pub use result::*; 7 | mod block_number; 8 | pub use block_number::*; 9 | mod block_hash; 10 | pub use block_hash::*; 11 | mod service_id; 12 | pub use service_id::*; 13 | mod block_events; 14 | pub use block_events::*; 15 | mod caller; 16 | pub use caller::*; 17 | mod list; 18 | pub use list::*; 19 | mod optional; 20 | pub use optional::*; 21 | -------------------------------------------------------------------------------- /crates/networking/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 2 | 3 | pub mod behaviours; 4 | pub mod blueprint_protocol; 5 | pub mod discovery; 6 | pub mod error; 7 | pub mod service; 8 | pub mod service_handle; 9 | pub mod types; 10 | 11 | #[cfg(feature = "testing")] 12 | pub mod test_utils; 13 | 14 | #[cfg(test)] 15 | mod tests; 16 | 17 | pub use blueprint_crypto::KeyType; 18 | pub use service::{AllowedKeys, NetworkConfig, NetworkEvent, NetworkService}; 19 | -------------------------------------------------------------------------------- /crates/stores/local-database/src/error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can occur while interacting with the [`LocalDatabase`] 2 | /// 3 | /// [`LocalDatabase`]: crate::LocalDatabase 4 | #[derive(thiserror::Error, Debug)] 5 | pub enum Error { 6 | /// Errors during I/O operations 7 | #[error(transparent)] 8 | Io(#[from] std::io::Error), 9 | /// Errors serializing or deserializing the database 10 | #[error(transparent)] 11 | Serialization(#[from] serde_json::Error), 12 | } 13 | -------------------------------------------------------------------------------- /cli/src/command/create/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error("Failed to generate blueprint: {0}")] 4 | GenerationFailed(anyhow::Error), 5 | #[error("Failed to initialize submodules, see .gitmodules to add them manually")] 6 | SubmoduleInit, 7 | #[error("{0}")] 8 | Io(#[from] std::io::Error), 9 | #[error("Missing required template variables when --skip-prompts is used: {0}")] 10 | MissingTemplateVariables(String), 11 | } 12 | -------------------------------------------------------------------------------- /crates/stores/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Storage providers for the Blueprint SDK 2 | //! 3 | //! ## Features 4 | #![doc = document_features::document_features!()] 5 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 6 | #![doc( 7 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 8 | )] 9 | 10 | pub mod error; 11 | pub use error::Error; 12 | 13 | #[cfg(feature = "local")] 14 | pub use blueprint_store_local_database as local_database; 15 | -------------------------------------------------------------------------------- /crates/evm-extra/src/extract/mod.rs: -------------------------------------------------------------------------------- 1 | //! Extraction utilities for EVM-specific data 2 | //! 3 | //! This module provides extractors for EVM blocks and events, following the same 4 | //! pattern as Tangle for consistency and reusability. 5 | 6 | pub mod block; 7 | pub mod contract; 8 | pub mod event; 9 | pub mod tx; 10 | 11 | pub use block::{BlockHash, BlockNumber, BlockTimestamp}; 12 | pub use contract::ContractAddress; 13 | pub use event::{BlockEvents, Events, FirstEvent, LastEvent}; 14 | pub use tx::Tx; 15 | -------------------------------------------------------------------------------- /examples/incredible-squaring/contracts/src/ExperimentalBlueprint.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSE 2 | pragma solidity >=0.8.13; 3 | 4 | import "tnt-core/BlueprintServiceManagerBase.sol"; 5 | 6 | /** 7 | * @title ExperimentalBlueprint 8 | * @dev This contract is an example of a service blueprint that provides a single service. 9 | * @dev For all supported hooks, check the `BlueprintServiceManagerBase` contract. 10 | */ 11 | contract ExperimentalBlueprint is BlueprintServiceManagerBase { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /crates/crypto/tangle-pair-signer/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_crypto_sp_core::error::SecretStringErrorWrapper; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Error)] 5 | pub enum TanglePairSignerError { 6 | #[error("Invalid secret string: {0}")] 7 | SecretStringError(SecretStringErrorWrapper), 8 | #[cfg(feature = "evm")] 9 | #[error("Ecdsa k256 error: {0}")] 10 | EcdsaError(#[from] k256::ecdsa::Error), 11 | } 12 | 13 | pub type Result = blueprint_std::result::Result; 14 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/extract_self_ref.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::{FromJobCall, JobCall}; 3 | 4 | struct A; 5 | 6 | impl FromJobCall for A 7 | where 8 | Ctx: Send + Sync, 9 | { 10 | type Rejection = (); 11 | 12 | async fn from_job_call(_call: JobCall, _ctx: &Ctx) -> Result { 13 | unimplemented!() 14 | } 15 | } 16 | 17 | impl A { 18 | #[debug_job] 19 | async fn job(&self) {} 20 | } 21 | 22 | fn main() {} 23 | -------------------------------------------------------------------------------- /crates/metrics/rpc-calls/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-metrics-rpc-calls" 3 | version = "0.1.0-alpha.3" 4 | description = "RPC call metrics for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | metrics = { workspace = true } 17 | 18 | [features] 19 | default = ["std"] 20 | std = [] 21 | -------------------------------------------------------------------------------- /crates/core/src/extract/rejection.rs: -------------------------------------------------------------------------------- 1 | //! Rejection response types. 2 | 3 | use crate::__define_rejection as define_rejection; 4 | 5 | define_rejection! { 6 | #[body = "Request body didn't contain valid UTF-8"] 7 | /// Rejection type used when buffering a [`JobCall`] into a [`String`] if the 8 | /// body doesn't contain valid UTF-8. 9 | /// 10 | /// [`JobCall`]: crate::JobCall 11 | /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html 12 | pub struct InvalidUtf8(Error); 13 | } 14 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/tests.rs: -------------------------------------------------------------------------------- 1 | mod ui; 2 | 3 | #[cfg(test)] 4 | mod tests { 5 | #[test] 6 | fn test_derive_context() { 7 | let t = trybuild::TestCases::new(); 8 | t.pass("tests/ui/basic.rs"); 9 | t.pass("tests/ui/unnamed_fields.rs"); 10 | t.pass("tests/ui/generic_struct.rs"); 11 | t.compile_fail("tests/ui/missing_config_attr.rs"); 12 | t.compile_fail("tests/ui/not_a_struct.rs"); 13 | t.compile_fail("tests/ui/unit_struct.rs"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/extract_self_mut.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::{FromJobCall, JobCall}; 3 | 4 | struct A; 5 | 6 | impl FromJobCall for A 7 | where 8 | Ctx: Send + Sync, 9 | { 10 | type Rejection = (); 11 | 12 | async fn from_job_call(_call: JobCall, _ctx: &Ctx) -> Result { 13 | unimplemented!() 14 | } 15 | } 16 | 17 | impl A { 18 | #[debug_job] 19 | async fn job(&mut self) {} 20 | } 21 | 22 | fn main() {} 23 | -------------------------------------------------------------------------------- /.github/actions/free-disk-space/action.yml: -------------------------------------------------------------------------------- 1 | name: Free disk space 2 | description: We've run into out-of-disk error when compiling Rust projects, so we free up some space this way. 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Free Disk Space 8 | uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 1.3.1 9 | with: 10 | android: true # This alone is a 12 GB save. 11 | large-packages: false 12 | swap-storage: false 13 | -------------------------------------------------------------------------------- /crates/crypto/bn254/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Clone, Error)] 5 | pub enum Bn254Error { 6 | #[error("Invalid seed: {0}")] 7 | InvalidSeed(String), 8 | #[error("Invalid signature: {0}")] 9 | SignatureFailed(String), 10 | #[error("Signature not in subgroup")] 11 | SignatureNotInSubgroup, 12 | #[error("Invalid input: {0}")] 13 | InvalidInput(String), 14 | } 15 | 16 | pub type Result = blueprint_std::result::Result; 17 | -------------------------------------------------------------------------------- /crates/router/src/util.rs: -------------------------------------------------------------------------------- 1 | pub(crate) fn try_downcast(k: K) -> Result 2 | where 3 | T: 'static, 4 | K: Send + 'static, 5 | { 6 | let mut k = Some(k); 7 | if let Some(k) = ::downcast_mut::>(&mut k) { 8 | Ok(k.take().unwrap()) 9 | } else { 10 | Err(k.unwrap()) 11 | } 12 | } 13 | 14 | #[test] 15 | fn test_try_downcast() { 16 | assert_eq!(try_downcast::(5_u32), Err(5_u32)); 17 | assert_eq!(try_downcast::(5_i32), Ok(5_i32)); 18 | } 19 | -------------------------------------------------------------------------------- /crates/producers-extra/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Extra producers for the Blueprint SDK 2 | //! 3 | //! This is a catch-all crate for extra producers that are not protocol specific. 4 | //! 5 | //! ## Features 6 | #![doc = document_features::document_features!()] 7 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 8 | #![doc( 9 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 10 | )] 11 | 12 | #[cfg_attr(not(feature = "std"), no_std)] 13 | #[cfg(feature = "cron")] 14 | pub mod cron; 15 | -------------------------------------------------------------------------------- /examples/incredible-squaring/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "incredible-squaring-env", 3 | "version": "0.1.0", 4 | "main": "index.js", 5 | "author": "Webb ", 6 | "license": "Unlicense", 7 | "private": true, 8 | "type": "module", 9 | "devDependencies": { 10 | "@types/node": "20.14.10", 11 | "prettier": "3.3.3", 12 | "tsx": "4.16.2", 13 | "typescript": "5.5.3" 14 | }, 15 | "dependencies": { 16 | "@polkadot/api": "^12.2.1", 17 | "tslib": "^2.6.3", 18 | "viem": "^2.17.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /crates/macros/tests/from_ref/pass/basic.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::{Router, extract::{FromRef, Context}}; 2 | 3 | // This will implement `FromRef` for each field in the struct. 4 | #[derive(Clone, FromRef)] 5 | struct AppContext { 6 | auth_token: String, 7 | } 8 | 9 | // So those types can be extracted via `Context` 10 | async fn job(_: Context) {} 11 | 12 | fn main() { 13 | let ctx = AppContext { 14 | auth_token: Default::default(), 15 | }; 16 | 17 | let _: Router = Router::new().route(0, job).with_context(ctx); 18 | } 19 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Rust build artifacts 2 | target/ 3 | **/target/ 4 | 5 | # Git 6 | .git/ 7 | .gitignore 8 | 9 | # IDE 10 | .vscode/ 11 | .idea/ 12 | *.swp 13 | *.swo 14 | *~ 15 | 16 | # Node 17 | node_modules/ 18 | **/node_modules/ 19 | 20 | # Logs 21 | *.log 22 | **/*.log 23 | 24 | # Test artifacts 25 | *.profdata 26 | *.profraw 27 | 28 | # Docker 29 | Dockerfile 30 | .dockerignore 31 | 32 | # CI/CD 33 | .github/ 34 | .gitlab-ci.yml 35 | 36 | # Documentation 37 | *.md 38 | !README.md 39 | docs/ 40 | 41 | # Temporary files 42 | *.tmp 43 | .DS_Store 44 | -------------------------------------------------------------------------------- /crates/metrics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-metrics" 3 | version = "0.1.0-alpha.3" 4 | description = "Metrics metapackage for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-metrics-rpc-calls = { workspace = true, optional = true } 17 | 18 | [features] 19 | default = ["rpc-calls"] 20 | rpc-calls = ["dep:blueprint-metrics-rpc-calls"] 21 | -------------------------------------------------------------------------------- /crates/contexts/src/eigenlayer.rs: -------------------------------------------------------------------------------- 1 | use blueprint_clients::Error; 2 | pub use blueprint_clients::eigenlayer::client::EigenlayerClient; 3 | use blueprint_runner::config::BlueprintEnvironment; 4 | 5 | /// Provides access to Eigenlayer utilities through its [`EigenlayerClient`]. 6 | pub trait EigenlayerContext { 7 | async fn eigenlayer_client(&self) -> Result; 8 | } 9 | 10 | impl EigenlayerContext for BlueprintEnvironment { 11 | async fn eigenlayer_client(&self) -> Result { 12 | Ok(EigenlayerClient::new(self.clone())) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/incredible-squaring/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "NodeNext", 6 | "lib": [ 7 | "ESNext" 8 | ], 9 | "moduleResolution": "Node", 10 | "strict": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "esModuleInterop": true, 14 | "noEmit": false, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "noImplicitReturns": true, 18 | "skipLibCheck": true 19 | }, 20 | "include": [ 21 | "./*.ts" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/set_ctx.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::{FromJobCall, JobCall, extract::FromRef}; 3 | 4 | #[debug_job(context = AppContext)] 5 | async fn handler(_: A) {} 6 | 7 | #[derive(Clone)] 8 | struct AppContext; 9 | 10 | struct A; 11 | 12 | impl FromJobCall for A 13 | where 14 | Ctx: Send + Sync, 15 | AppContext: FromRef, 16 | { 17 | type Rejection = (); 18 | 19 | async fn from_job_call(_call: JobCall, _ctx: &Ctx) -> Result { 20 | unimplemented!() 21 | } 22 | } 23 | 24 | fn main() {} 25 | -------------------------------------------------------------------------------- /examples/incredible-squaring/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | target/ 3 | 4 | # These are backup files generated by rustfmt 5 | **/*.rs.bk 6 | 7 | # MSVC Windows builds of rustc generate these, which store debugging information 8 | *.pdb 9 | 10 | .idea 11 | .vscode 12 | .zed 13 | 14 | .direnv 15 | .DS_Store 16 | # Solc Compiler files 17 | cache/ 18 | out/ 19 | 20 | # Ignores development broadcast logs 21 | !/broadcast 22 | /broadcast/*/31337/ 23 | /broadcast/**/dry-run/ 24 | 25 | # Docs 26 | docs/ 27 | 28 | # Dotenv file 29 | .env 30 | 31 | # Blueprint metadata 32 | blueprint.json 33 | blueprint.lock 34 | -------------------------------------------------------------------------------- /crates/manager/src/protocol/eigenlayer/mod.rs: -------------------------------------------------------------------------------- 1 | /// EigenLayer Protocol implementation for blueprint manager 2 | /// 3 | /// This module contains the EigenLayer-specific client, event handler, and registration management. 4 | pub mod client; 5 | pub mod event_handler; 6 | 7 | pub use client::EigenlayerProtocolClient; 8 | pub use event_handler::EigenlayerEventHandler; 9 | 10 | // Re-export registration types from blueprint-eigenlayer-extra 11 | pub use blueprint_eigenlayer_extra::registration::{ 12 | AvsRegistration, AvsRegistrationConfig, AvsRegistrations, RegistrationStateManager, 13 | RegistrationStatus, 14 | }; 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "cargo" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" -------------------------------------------------------------------------------- /crates/clients/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-client-core" 3 | version = "0.1.0-alpha.4" 4 | description = "Core primitives for Tangle Blueprint clients" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-std = { workspace = true } 17 | auto_impl = { workspace = true } 18 | thiserror = { workspace = true } 19 | 20 | [features] 21 | default = ["std"] 22 | std = [ 23 | "blueprint-std/std", 24 | ] 25 | -------------------------------------------------------------------------------- /crates/contexts/src/keystore.rs: -------------------------------------------------------------------------------- 1 | use blueprint_keystore::Keystore; 2 | 3 | /// `KeystoreContext` trait provides access to the generic keystore from the context. 4 | pub trait KeystoreContext { 5 | /// Get the keystore client from the context. 6 | fn keystore(&self) -> Keystore; 7 | } 8 | 9 | #[cfg(feature = "std")] 10 | impl KeystoreContext for blueprint_runner::config::BlueprintEnvironment { 11 | fn keystore(&self) -> Keystore { 12 | let config = blueprint_keystore::KeystoreConfig::new().fs_root(self.keystore_uri.clone()); 13 | Keystore::new(config).expect("Failed to create keystore") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/incredible-squaring/incredible-squaring-bin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "incredible-squaring-blueprint-bin" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [dependencies] 8 | incredible-squaring-blueprint-lib.workspace = true 9 | 10 | blueprint-sdk = { workspace = true, features = ["std", "tangle"] } 11 | tokio = { workspace = true, features = ["rt-multi-thread"] } 12 | tower.workspace = true 13 | 14 | [build-dependencies] 15 | incredible-squaring-blueprint-lib.workspace = true 16 | blueprint-sdk = { workspace = true, features = ["macros", "build", "testing"] } 17 | -------------------------------------------------------------------------------- /examples/oauth-blueprint/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "contracts/src" 3 | test = "contracts/test" 4 | out = "contracts/out" 5 | script = "contracts/script" 6 | cache_path = "contracts/cache" 7 | broadcast = "contracts/broadcast" 8 | libs = ["dependencies"] 9 | auto_detect_remappings = true 10 | 11 | [soldeer] 12 | recursive_deps = true 13 | remappings_location = "txt" 14 | remappings_version = false 15 | 16 | [dependencies] 17 | tnt-core = { version = "0.5.0", git = "https://github.com/tangle-network/tnt-core" } 18 | 19 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 20 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "contracts/src" 3 | test = "contracts/test" 4 | out = "contracts/out" 5 | script = "contracts/script" 6 | cache_path = "contracts/cache" 7 | broadcast = "contracts/broadcast" 8 | libs = ["dependencies"] 9 | auto_detect_remappings = true 10 | 11 | [soldeer] 12 | recursive_deps = true 13 | remappings_location = "txt" 14 | remappings_version = false 15 | 16 | [dependencies] 17 | tnt-core = { version = "0.5.0", git = "https://github.com/tangle-network/tnt-core" } 18 | 19 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 20 | -------------------------------------------------------------------------------- /examples/incredible-squaring/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "contracts/src" 3 | test = "contracts/test" 4 | out = "contracts/out" 5 | script = "contracts/script" 6 | cache_path = "contracts/cache" 7 | broadcast = "contracts/broadcast" 8 | libs = ["dependencies"] 9 | auto_detect_remappings = true 10 | 11 | [soldeer] 12 | recursive_deps = true 13 | remappings_location = "txt" 14 | remappings_version = false 15 | 16 | [dependencies] 17 | tnt-core = { version = "0.5.0", git = "https://github.com/tangle-network/tnt-core" } 18 | 19 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 20 | -------------------------------------------------------------------------------- /examples/oauth-blueprint/oauth-blueprint-bin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oauth-blueprint-bin" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | oauth-blueprint-lib = { path = "../oauth-blueprint-lib" } 8 | blueprint-sdk = { path = "../../../crates/sdk", features = ["std", "tangle"] } 9 | tokio = { version = "^1", features = ["rt-multi-thread", "macros"] } 10 | tower = { version = "0.5.2" } 11 | tracing-subscriber = { version = "0.3" } 12 | 13 | [build-dependencies] 14 | oauth-blueprint-lib = { path = "../oauth-blueprint-lib" } 15 | blueprint-sdk = { path = "../../../crates/sdk", features = ["macros", "build", "testing"] } 16 | -------------------------------------------------------------------------------- /crates/testing-utils/tangle/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use blueprint_core_testing_utils::Error; 2 | use tangle_subxt::subxt_core::utils::AccountId32; 3 | 4 | #[cfg(test)] 5 | mod tests; 6 | 7 | pub mod blueprint; 8 | pub mod harness; 9 | pub mod keys; 10 | pub mod multi_node; 11 | pub mod runner; 12 | 13 | // Re-export commonly used types 14 | pub use harness::TangleTestHarness; 15 | 16 | pub type InputValue = tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::Field; 17 | pub type OutputValue = tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::Field; 18 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/apikey-blueprint-bin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "apikey-blueprint-bin" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | apikey-blueprint-lib = { path = "../apikey-blueprint-lib" } 8 | blueprint-sdk = { path = "../../../crates/sdk", features = ["std", "tangle"] } 9 | tokio = { version = "^1", features = ["rt-multi-thread", "macros"] } 10 | tower = { version = "0.5.2" } 11 | tracing-subscriber = { version = "0.3" } 12 | 13 | [build-dependencies] 14 | apikey-blueprint-lib = { path = "../apikey-blueprint-lib" } 15 | blueprint-sdk = { path = "../../../crates/sdk", features = ["macros", "build", "testing"] } 16 | -------------------------------------------------------------------------------- /crates/manager/src/rt/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "containers")] 2 | pub mod container; 3 | #[cfg(feature = "vm-sandbox")] 4 | pub mod hypervisor; 5 | pub mod native; 6 | pub mod service; 7 | 8 | pub struct ResourceLimits { 9 | /// Allocated storage space in bytes 10 | pub storage_space: u64, 11 | /// Allocated memory space in bytes 12 | pub memory_size: u64, 13 | } 14 | 15 | impl Default for ResourceLimits { 16 | fn default() -> Self { 17 | Self { 18 | // 20GB 19 | storage_space: 1024 * 1024 * 1024 * 20, 20 | // 4GB 21 | memory_size: 1024 * 1024 * 1024 * 4, 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | target/ 3 | tmp/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | 8 | # MSVC Windows builds of rustc generate these, which store debugging information 9 | *.pdb 10 | 11 | .idea 12 | .vscode 13 | .zed 14 | 15 | .direnv 16 | .DS_Store 17 | # Solc Compiler files 18 | cache/ 19 | out/ 20 | 21 | # Ignores development broadcast logs 22 | !/broadcast 23 | /broadcast/*/31337/ 24 | /broadcast/**/dry-run/ 25 | 26 | # Docs 27 | docs/ 28 | 29 | # Dotenv file 30 | .env 31 | 32 | 33 | # Soldeer 34 | /dependencies 35 | 36 | # keystore 37 | test-keystore/ 38 | keystore/ 39 | 40 | -------------------------------------------------------------------------------- /crates/crypto/bls/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Clone, Error)] 5 | pub enum BlsError { 6 | #[error("Invalid seed: {0}")] 7 | InvalidSeed(String), 8 | #[error("Invalid hex string: {0}")] 9 | HexError(hex::FromHexError), 10 | #[error("Invalid signature")] 11 | InvalidSignature, 12 | #[error("Invalid input")] 13 | InvalidInput(String), 14 | } 15 | 16 | impl From for BlsError { 17 | fn from(error: hex::FromHexError) -> Self { 18 | BlsError::HexError(error) 19 | } 20 | } 21 | 22 | pub type Result = blueprint_std::result::Result; 23 | -------------------------------------------------------------------------------- /crates/qos/config/grafana_dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "dashboard": { 3 | "title": "Blueprint QoS Dashboard", 4 | "panels": [ 5 | { 6 | "title": "Job Executions (Test)", 7 | "type": "stat", 8 | "targets": [ 9 | { 10 | "expr": "sum(rate(otel_job_executions_total[$__rate_interval]))", 11 | "legendFormat": "Executions / sec" 12 | } 13 | ], 14 | "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 } 15 | } 16 | ], 17 | "time": { 18 | "from": "now-5m", 19 | "to": "now" 20 | }, 21 | "timezone": "browser" 22 | }, 23 | "folderId": 0, 24 | "overwrite": true 25 | } 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | king: 4 | build: 5 | context: . 6 | dockerfile: ./docker/server/Dockerfile 7 | environment: 8 | - BIND_ADDRESS=0.0.0.0:5555 9 | ports: 10 | - 5555:5555 11 | networks: 12 | zk_network: 13 | ipv4_address: 172.40.0.10 14 | 15 | clients: 16 | build: 17 | context: . 18 | dockerfile: ./docker/client/Dockerfile 19 | environment: 20 | - SERVER_IP=172.40.0.10 21 | - SERVER_PORT=5555 22 | networks: 23 | - zk_network 24 | 25 | networks: 26 | zk_network: 27 | driver: bridge 28 | ipam: 29 | config: 30 | - subnet: 172.40.0.0/16 -------------------------------------------------------------------------------- /examples/incredible-squaring/incredible-squaring-lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "incredible-squaring-blueprint-lib" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [dependencies] 8 | blueprint-sdk = { workspace = true, features = ["std", "tangle", "macros"] } 9 | tokio = { workspace = true, features = ["sync"] } 10 | 11 | [dev-dependencies] 12 | blueprint-sdk = { workspace = true, features = ["testing", "tangle"] } 13 | tokio = { workspace = true, features = ["macros"] } 14 | color-eyre = { workspace = true } 15 | 16 | [package.metadata.blueprint] 17 | manager = { Evm = "ExperimentalBlueprint" } 18 | master_revision = "Latest" 19 | -------------------------------------------------------------------------------- /examples/incredible-squaring/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["incredible-squaring-lib", "incredible-squaring-bin"] 4 | 5 | [workspace.package] 6 | version = "0.1.1" 7 | description = "An experimental blueprint" 8 | edition = "2024" 9 | rust-version = "1.85" 10 | 11 | [workspace.dependencies] 12 | incredible-squaring-blueprint-lib = { path = "incredible-squaring-lib" } 13 | 14 | blueprint-sdk = { path = "../../crates/sdk", default-features = false } 15 | tokio = { version = "^1", default-features = false } 16 | color-eyre = "0.6" 17 | tower = { version = "0.5.2", default-features = false } 18 | tracing-subscriber = { version = "0.3", features = ["env-filter"] } 19 | -------------------------------------------------------------------------------- /crates/benchmarking/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-benchmarking" 3 | version = "0.1.0-alpha.5" 4 | description = "Utilities for benchmarking Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-std = { workspace = true } 17 | sysinfo = { workspace = true, optional = true, features = ["system"] } 18 | tokio = { workspace = true, features = ["sync", "time"] } 19 | 20 | [features] 21 | default = ["std"] 22 | std = ["dep:sysinfo", "blueprint-std/std", "tokio/full"] 23 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/infer_context.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::extract::Context; 3 | 4 | #[debug_job] 5 | async fn job(_: Context) {} 6 | 7 | #[debug_job] 8 | async fn job_2(_: blueprint_sdk::extract::Context) {} 9 | 10 | #[debug_job] 11 | async fn job_3(_: blueprint_sdk::extract::Context, _: blueprint_sdk::extract::Context) {} 12 | 13 | #[debug_job] 14 | async fn job_4(_: Context, _: Context) {} 15 | 16 | #[debug_job] 17 | async fn job_5(_: blueprint_sdk::extract::Context, _: Context) {} 18 | 19 | #[derive(Clone)] 20 | struct AppContext; 21 | 22 | fn main() {} 23 | -------------------------------------------------------------------------------- /crates/keystore/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 3 | 4 | macro_rules! cfg_remote { 5 | ($($item:item)*) => { 6 | $( 7 | #[cfg(any( 8 | feature = "aws-signer", 9 | feature = "gcp-signer", 10 | feature = "ledger-browser", 11 | feature = "ledger-node" 12 | ))] 13 | $item 14 | )* 15 | }; 16 | } 17 | 18 | pub(crate) use cfg_remote; 19 | 20 | pub mod error; 21 | pub use error::*; 22 | mod keystore; 23 | pub use keystore::*; 24 | 25 | pub use blueprint_crypto as crypto; 26 | 27 | cfg_remote! { 28 | pub mod remote; 29 | } 30 | 31 | pub mod storage; 32 | -------------------------------------------------------------------------------- /workspace-hack/Cargo.toml: -------------------------------------------------------------------------------- 1 | # This file is generated by `cargo hakari`. 2 | # To regenerate, run: 3 | # cargo hakari generate 4 | 5 | [package] 6 | name = "workspace-hack" 7 | version = "0.1.0" 8 | edition = "2021" 9 | description = "workspace-hack package, managed by hakari" 10 | # You can choose to publish this crate: see https://docs.rs/cargo-hakari/latest/cargo_hakari/publishing. 11 | publish = false 12 | 13 | # The parts of the file between the BEGIN HAKARI SECTION and END HAKARI SECTION comments 14 | # are managed by hakari. 15 | 16 | ### BEGIN HAKARI SECTION 17 | 18 | # Disabled by running `cargo hakari disable`. 19 | # To re-enable, run: 20 | # cargo hakari generate 21 | ### END HAKARI SECTION 22 | -------------------------------------------------------------------------------- /crates/stores/local-database/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-store-local-database" 3 | version = "0.1.0-alpha.7" 4 | description = "Local database storage provider for the Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-std = { workspace = true, features = ["std"] } 17 | serde = { workspace = true, features = ["derive"] } 18 | serde_json = { workspace = true, features = ["std"] } 19 | thiserror = { workspace = true } 20 | 21 | [dev-dependencies] 22 | tempfile = { workspace = true } 23 | -------------------------------------------------------------------------------- /crates/contexts/src/tangle.rs: -------------------------------------------------------------------------------- 1 | pub use blueprint_clients::Error; 2 | pub use blueprint_clients::tangle::client::TangleClient; 3 | use blueprint_runner::config::BlueprintEnvironment; 4 | 5 | /// `TangleContext` trait provides access to the Tangle client from the context. 6 | pub trait TangleClientContext { 7 | /// Returns the Tangle client instance 8 | async fn tangle_client(&self) -> Result; 9 | } 10 | 11 | impl TangleClientContext for BlueprintEnvironment { 12 | async fn tangle_client(&self) -> Result { 13 | let keystore = self.keystore(); 14 | TangleClient::with_keystore(self.clone(), keystore) 15 | .await 16 | .map_err(Into::into) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /crates/clients/evm/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Error)] 5 | pub enum Error { 6 | #[error("Provider error: {0}")] 7 | Provider(String), 8 | #[error("Invalid address: {0}")] 9 | InvalidAddress(String), 10 | #[error("Transaction error: {0}")] 11 | Transaction(String), 12 | #[error("Contract error: {0}")] 13 | Contract(String), 14 | #[error("ABI error: {0}")] 15 | Abi(String), 16 | } 17 | 18 | impl From for blueprint_client_core::error::Error { 19 | fn from(value: Error) -> Self { 20 | blueprint_client_core::error::Error::Evm(value.to_string()) 21 | } 22 | } 23 | 24 | pub type Result = blueprint_std::result::Result; 25 | -------------------------------------------------------------------------------- /crates/runner/src/tangle/error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can occur within the Tangle protocol runner 2 | #[derive(Debug, thiserror::Error)] 3 | pub enum TangleError { 4 | /// Attempted registration despite not being an active operator 5 | #[error("Not an active operator")] 6 | NotActiveOperator, 7 | 8 | #[error("Network error: {0}")] 9 | Network(tangle_subxt::subxt::Error), 10 | 11 | /// Unable to open/interact with the provided [`Keystore`](blueprint_keystore::Keystore) 12 | #[error("Keystore error: {0}")] 13 | Keystore(#[from] blueprint_keystore::Error), 14 | 15 | /// Unable to decompress the provided ECDSA key 16 | #[error("Unable to convert compressed ECDSA key to uncompressed key")] 17 | DecompressEcdsaKey, 18 | } 19 | -------------------------------------------------------------------------------- /cli/src/utils.rs: -------------------------------------------------------------------------------- 1 | use dialoguer::console::style; 2 | 3 | /// Print a section header with consistent styling 4 | pub fn print_section_header(title: &str) { 5 | println!("\n{}", style(format!("━━━ {} ━━━", title)).cyan().bold()); 6 | } 7 | 8 | /// Print a success message with an emoji and optional details 9 | pub fn print_success(message: &str, details: Option<&str>) { 10 | println!( 11 | "\n{} {}{}", 12 | style("✓").green().bold(), 13 | style(message).green(), 14 | details.map_or(String::new(), |d| format!("\n {}", style(d).dim())) 15 | ); 16 | } 17 | 18 | /// Print an info message with consistent styling 19 | pub fn print_info(message: &str) { 20 | println!("{}", style(format!("ℹ {}", message)).blue()); 21 | } 22 | -------------------------------------------------------------------------------- /crates/networking/extensions/agg-sig-gossip/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod protocol; 2 | pub use protocol::{AggregationError, ProtocolConfig, SignatureAggregationProtocol}; 3 | 4 | // State management 5 | mod protocol_state; 6 | pub use protocol_state::{AggregationState, ProtocolRound}; 7 | 8 | // Aggregator selection 9 | mod aggregator_selection; 10 | pub use aggregator_selection::AggregatorSelector; 11 | 12 | // Malicious detection 13 | mod malicious; 14 | pub use malicious::MaliciousEvidence; 15 | 16 | // Message types 17 | mod messages; 18 | pub use messages::{AggSigMessage, AggregationResult}; 19 | 20 | // Signature weighting schemes 21 | mod signature_weight; 22 | pub use signature_weight::{CustomWeight, EqualWeight, SignatureWeight}; 23 | 24 | #[cfg(test)] 25 | mod tests; 26 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Counts the number of identifiers provided to the macro. 2 | /// 3 | /// This macro recursively counts the number of identifiers passed to it by 4 | /// processing each identifier and the rest of the token tree separately. 5 | /// 6 | /// # Examples 7 | /// 8 | /// ``` 9 | /// # use blueprint_tangle_extra::count; 10 | /// let c = count!(a, b, c, d); 11 | /// assert_eq!(c, 4); 12 | /// 13 | /// let empty_count = count!(); 14 | /// assert_eq!(empty_count, 0); 15 | /// ``` 16 | #[macro_export] 17 | #[doc(hidden)] 18 | macro_rules! count { 19 | ($val:ident, $($rest:tt)*) => { 20 | 1 + $crate::count!($($rest)*) 21 | }; 22 | ($val:ident) => { 23 | 1 24 | }; 25 | () => { 26 | 0 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/clients/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error(transparent)] 4 | Core(#[from] blueprint_client_core::error::Error), 5 | #[error(transparent)] 6 | #[cfg(feature = "eigenlayer")] 7 | Eigenlayer(#[from] blueprint_client_eigenlayer::error::Error), 8 | #[error(transparent)] 9 | #[cfg(feature = "evm")] 10 | Evm(#[from] blueprint_client_evm::error::Error), 11 | #[error(transparent)] 12 | #[cfg(feature = "tangle")] 13 | Tangle(#[from] blueprint_client_tangle::error::Error), 14 | } 15 | 16 | impl Error { 17 | pub fn msg(msg: T) -> Self { 18 | let err = blueprint_client_core::error::Error::msg(msg); 19 | Error::Core(err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /crates/manager/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! ![Tangle Network Banner](https://raw.githubusercontent.com/tangle-network/tangle/refs/heads/main/assets/Tangle%20%20Banner.png) 2 | //! 3 | //!

Blueprint Manager

4 | //! 5 | //! ## Features 6 | #![doc = document_features::document_features!()] 7 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 8 | #![doc( 9 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 10 | )] 11 | #![allow(clippy::module_name_repetitions)] 12 | 13 | pub mod blueprint; 14 | pub mod config; 15 | pub mod error; 16 | pub mod executor; 17 | pub mod protocol; 18 | pub mod rt; 19 | pub mod sdk; 20 | pub mod sources; 21 | 22 | pub use executor::run_blueprint_manager; 23 | 24 | pub use blueprint_auth; 25 | -------------------------------------------------------------------------------- /cli/src/command/debug/spawn/native.rs: -------------------------------------------------------------------------------- 1 | use blueprint_manager::config::BlueprintManagerContext; 2 | use blueprint_manager::rt::ResourceLimits; 3 | use blueprint_manager::rt::service::Service; 4 | use blueprint_manager::sources::{BlueprintArgs, BlueprintEnvVars}; 5 | use std::path::PathBuf; 6 | 7 | pub async fn setup_native( 8 | ctx: &BlueprintManagerContext, 9 | limits: ResourceLimits, 10 | service_name: &str, 11 | binary: PathBuf, 12 | env: BlueprintEnvVars, 13 | args: BlueprintArgs, 14 | ) -> color_eyre::Result { 15 | let service = Service::new_native( 16 | ctx, 17 | limits, 18 | ctx.runtime_dir(), 19 | service_name, 20 | binary, 21 | env, 22 | args, 23 | ) 24 | .await?; 25 | Ok(service) 26 | } 27 | -------------------------------------------------------------------------------- /cli/src/command/debug/spawn/container.rs: -------------------------------------------------------------------------------- 1 | use blueprint_manager::config::BlueprintManagerContext; 2 | use blueprint_manager::rt::ResourceLimits; 3 | use blueprint_manager::rt::service::Service; 4 | use blueprint_manager::sources::{BlueprintArgs, BlueprintEnvVars}; 5 | 6 | pub async fn setup_with_container( 7 | ctx: &BlueprintManagerContext, 8 | limits: ResourceLimits, 9 | service_name: &str, 10 | image: String, 11 | env: BlueprintEnvVars, 12 | args: BlueprintArgs, 13 | ) -> color_eyre::Result { 14 | let service = Service::new_container( 15 | ctx, 16 | limits, 17 | ctx.runtime_dir(), 18 | service_name, 19 | image, 20 | env, 21 | args, 22 | true, 23 | ) 24 | .await?; 25 | 26 | Ok(service) 27 | } 28 | -------------------------------------------------------------------------------- /cli/src/anvil/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error("Error occurred in Testnet: {0}")] 4 | Container(String), 5 | #[error("Failed to mine anvil blocks: {0}")] 6 | Mine(String), 7 | #[error("Error occurred while waiting for responses: {0}")] 8 | WaitResponse(String), 9 | #[error("Contract Error: {0}")] 10 | Contract(#[from] alloy_contract::Error), 11 | #[error("Transaction Error: {0}")] 12 | Transaction(#[from] alloy_provider::PendingTransactionError), 13 | #[error("Keystore error: {0}")] 14 | Keystore(#[from] blueprint_keystore::Error), 15 | } 16 | 17 | impl From for Error { 18 | fn from(e: tokio::time::error::Elapsed) -> Self { 19 | Error::WaitResponse(e.to_string()) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /crates/core/src/extract/from_ref.rs: -------------------------------------------------------------------------------- 1 | /// Used to do reference-to-value conversions thus not consuming the input value. 2 | /// 3 | /// This is mainly used with [`Context`] to extract "subcontexts" from a reference to main application 4 | /// state. 5 | /// 6 | /// See [`Context`] for more details on how library authors should use this trait. 7 | /// 8 | /// This trait can be derived using `#[derive(FromRef)]`. 9 | /// 10 | /// [`Context`]: https://docs.rs/blueprint_sdk/latest/blueprint_sdk/extract/struct.Context.html 11 | pub trait FromRef { 12 | /// Converts to this type from a reference to the input type. 13 | fn from_ref(input: &T) -> Self; 14 | } 15 | 16 | impl FromRef for T 17 | where 18 | T: Clone, 19 | { 20 | fn from_ref(input: &T) -> Self { 21 | input.clone() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crates/stores/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-stores" 3 | version = "0.1.0-alpha.8" 4 | description = "Storage providers for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-store-local-database = { workspace = true, optional = true } 17 | thiserror.workspace = true 18 | document-features = { workspace = true, features = ["default"] } 19 | 20 | [features] 21 | default = ["local"] 22 | 23 | ## Enable the local KV store 24 | local = ["dep:blueprint-store-local-database"] 25 | 26 | [package.metadata.docs.rs] 27 | all-features = true 28 | rustdoc-args = ["--cfg", "docsrs"] 29 | -------------------------------------------------------------------------------- /crates/keystore/tests/construction.rs: -------------------------------------------------------------------------------- 1 | use blueprint_crypto::sp_core::SpEcdsa; 2 | use blueprint_keystore::Result; 3 | use blueprint_keystore::backends::Backend; 4 | use blueprint_keystore::backends::tangle::TangleBackend; 5 | use blueprint_keystore::{Keystore, KeystoreConfig}; 6 | 7 | #[test] 8 | fn fs_keystore() -> Result<()> { 9 | const EXPECTED: &[u8] = b"03065d2080364c71dccbdc7e3f552dc3a4501e02751211d06d4898e8e0e0509e30"; 10 | 11 | let tmp_dir = tempfile::tempdir()?; 12 | let keystore = Keystore::new(KeystoreConfig::new().fs_root(tmp_dir.path()))?; 13 | 14 | keystore.ecdsa_generate_from_string("//Foo")?; 15 | 16 | let ecdsa_keys = keystore.list_local::()?; 17 | assert_eq!(ecdsa_keys.len(), 1); 18 | assert_eq!(ecdsa_keys[0].0.0, &*hex::decode(EXPECTED).unwrap()); 19 | 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /crates/clients/tangle/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | pub mod client; 3 | pub mod error; 4 | pub mod services; 5 | 6 | #[cfg(not(any(feature = "std", feature = "web")))] 7 | compile_error!("`std` or `web` feature required"); 8 | 9 | use auto_impl::auto_impl; 10 | 11 | #[auto_impl(Arc)] 12 | pub trait EventsClient: Clone + Send + Sync { 13 | /// Fetch the next event from the client. 14 | async fn next_event(&self) -> Option; 15 | /// Fetch the latest event from the client. 16 | /// 17 | /// If no event has yet been fetched, the client will call [`next_event`](Self::next_event). 18 | async fn latest_event(&self) -> Option; 19 | } 20 | 21 | // NOTE: Actual client tests are in blueprint-tangle-testing-utils 22 | #[test] 23 | fn it_works() { 24 | assert_eq!(2 + 2, 4); 25 | } 26 | -------------------------------------------------------------------------------- /crates/router/src/test_helpers/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::disallowed_names)] 2 | 3 | use blueprint_core::__private::tracing::level_filters::LevelFilter; 4 | 5 | pub(crate) fn assert_send() {} 6 | pub(crate) fn assert_sync() {} 7 | #[allow(dead_code)] 8 | pub(crate) struct NotSendSync(*const ()); 9 | 10 | pub fn setup_log() { 11 | use tracing_subscriber::util::SubscriberInitExt; 12 | 13 | let _ = tracing_subscriber::fmt::SubscriberBuilder::default() 14 | .without_time() 15 | .with_span_events(tracing_subscriber::fmt::format::FmtSpan::NONE) 16 | .with_env_filter( 17 | tracing_subscriber::EnvFilter::builder() 18 | .with_default_directive(LevelFilter::INFO.into()) 19 | .from_env_lossy(), 20 | ) 21 | .finish() 22 | .try_init(); 23 | } 24 | -------------------------------------------------------------------------------- /crates/core/src/extract/metadata.rs: -------------------------------------------------------------------------------- 1 | //! An extractor for all metadata in the current [`JobCall`]. 2 | //! 3 | //! [`JobCall`]: crate::JobCall 4 | 5 | use core::convert::Infallible; 6 | 7 | use crate::FromJobCallParts; 8 | use crate::job::call::Parts as JobCallParts; 9 | use crate::metadata::{MetadataMap, MetadataValue}; 10 | 11 | /// Extractor for all metadata in the current [`JobCall`]. 12 | /// 13 | /// [`JobCall`]: crate::JobCall 14 | pub struct Metadata(pub MetadataMap); 15 | 16 | impl FromJobCallParts for Metadata 17 | where 18 | Ctx: Send + Sync + 'static, 19 | { 20 | type Rejection = Infallible; 21 | 22 | async fn from_job_call_parts( 23 | parts: &mut JobCallParts, 24 | _: &Ctx, 25 | ) -> Result { 26 | Ok(Metadata(parts.metadata.clone())) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/crypto/sr25519/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Clone, Error)] 5 | pub enum Sr25519Error { 6 | #[error("Invalid seed: {0}")] 7 | InvalidSeed(String), 8 | #[error("Invalid signature: {0}")] 9 | SignatureError(schnorrkel::SignatureError), 10 | #[error("Invalid hex string: {0}")] 11 | HexError(hex::FromHexError), 12 | } 13 | 14 | impl From for Sr25519Error { 15 | fn from(error: schnorrkel::SignatureError) -> Self { 16 | Sr25519Error::SignatureError(error) 17 | } 18 | } 19 | 20 | impl From for Sr25519Error { 21 | fn from(error: hex::FromHexError) -> Self { 22 | Sr25519Error::HexError(error) 23 | } 24 | } 25 | 26 | pub type Result = blueprint_std::result::Result; 27 | -------------------------------------------------------------------------------- /crates/crypto/hashing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-hashing" 3 | version = "0.1.0-alpha.5" 4 | description = "Hashing primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-std = { workspace = true } 14 | sha2 = { workspace = true, optional = true } 15 | sha3 = { workspace = true, optional = true } 16 | blake3 = { workspace = true, optional = true } 17 | 18 | [features] 19 | default = ["std", "sha2-hasher", "sha3-hasher", "blake3-hasher"] 20 | std = [ 21 | "blueprint-std/std", 22 | "sha2?/std", 23 | "sha3?/std", 24 | "blake3?/std", 25 | ] 26 | sha2-hasher = ["sha2"] 27 | sha3-hasher = ["sha3"] 28 | blake3-hasher = ["blake3"] 29 | -------------------------------------------------------------------------------- /crates/crypto/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-core" 3 | version = "0.1.0-alpha.9" 4 | description = "Core crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-std = { workspace = true } 14 | serde = { workspace = true, features = ["derive"] } 15 | thiserror = { workspace = true } 16 | clap = { workspace = true, optional = true } 17 | 18 | [features] 19 | default = ["std"] 20 | std = [ 21 | "serde/std", 22 | "blueprint-std/std", 23 | "clap?/std", 24 | ] 25 | 26 | # Crypto primitive features 27 | bn254 = [] 28 | k256 = [] 29 | sr25519-schnorrkel = [] 30 | bls = [] 31 | zebra = [] 32 | tangle = [] 33 | clap = ["dep:clap"] 34 | -------------------------------------------------------------------------------- /crates/crypto/k256/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Clone, Error)] 5 | pub enum K256Error { 6 | #[error("Invalid seed: {0}")] 7 | InvalidSeed(String), 8 | #[error("Invalid verifying key: {0}")] 9 | InvalidVerifyingKey(String), 10 | #[error("Invalid signing key: {0}")] 11 | InvalidSigner(String), 12 | #[error("Invalid hex string: {0}")] 13 | HexError(hex::FromHexError), 14 | #[error("Invalid signature: {0}")] 15 | InvalidSignature(String), 16 | #[error("Signature failed: {0}")] 17 | SignatureFailed(String), 18 | } 19 | 20 | impl From for K256Error { 21 | fn from(error: hex::FromHexError) -> Self { 22 | K256Error::HexError(error) 23 | } 24 | } 25 | 26 | pub type Result = blueprint_std::result::Result; 27 | -------------------------------------------------------------------------------- /crates/std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-std" 3 | version = "0.1.0-alpha.4" 4 | description = "Re-exports of core/std for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | rand = { workspace = true, features = ["std_rng"] } 17 | rayon = { workspace = true, optional = true } 18 | num-traits.workspace = true 19 | thiserror.workspace = true 20 | colored = { workspace = true } 21 | 22 | [dev-dependencies] 23 | rand = { workspace = true, features = ["std"] } 24 | 25 | [features] 26 | default = ["std"] 27 | std = ["thiserror/std", "getrandom"] 28 | parallel = ["dep:rayon", "std"] 29 | print-trace = ["std"] 30 | getrandom = ["rand/std"] 31 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Tangle Network Blueprint Extra functionality 2 | //! 3 | //! ## Features 4 | #![doc = document_features::document_features!()] 5 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 6 | #![doc( 7 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 8 | )] 9 | 10 | extern crate alloc; 11 | 12 | /// Tangle Network Job Consumers 13 | pub mod consumer; 14 | /// Tangle Specific extractors 15 | pub mod extract; 16 | /// Tangle Specific filters 17 | pub mod filters; 18 | /// Tangle Specific layers 19 | pub mod layers; 20 | /// Tangle Blueprint Build Metadata 21 | pub mod metadata; 22 | /// Tangle Network Job Producers 23 | pub mod producer; 24 | pub mod serde; 25 | #[cfg(any(feature = "std", feature = "web"))] 26 | pub mod util; 27 | 28 | pub use tangle_subxt::subxt_core; 29 | -------------------------------------------------------------------------------- /crates/chain-setup/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-chain-setup" 3 | version = "0.1.0-alpha.21" 4 | description = "Chain setup utilities for use with Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-chain-setup-tangle = { workspace = true, optional = true } 14 | blueprint-chain-setup-anvil = { workspace = true, optional = true } 15 | blueprint-chain-setup-common = { workspace = true } 16 | 17 | [features] 18 | default = ["std"] 19 | std = [ 20 | "blueprint-chain-setup-common/std", 21 | "blueprint-chain-setup-tangle?/std", 22 | "blueprint-chain-setup-anvil?/std", 23 | ] 24 | tangle = ["blueprint-chain-setup-tangle"] 25 | anvil = ["blueprint-chain-setup-anvil"] 26 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/pass/self_receiver.rs: -------------------------------------------------------------------------------- 1 | use blueprint_macros::debug_job; 2 | use blueprint_sdk::{FromJobCall, JobCall}; 3 | 4 | struct A; 5 | 6 | impl FromJobCall for A 7 | where 8 | Ctx: Send + Sync, 9 | { 10 | type Rejection = (); 11 | 12 | async fn from_job_call(_call: JobCall, _ctx: &Ctx) -> Result { 13 | unimplemented!() 14 | } 15 | } 16 | 17 | impl FromJobCall for Box 18 | where 19 | Ctx: Send + Sync, 20 | { 21 | type Rejection = (); 22 | 23 | async fn from_job_call(_call: JobCall, _ctx: &Ctx) -> Result { 24 | unimplemented!() 25 | } 26 | } 27 | 28 | impl A { 29 | #[debug_job] 30 | async fn job(self) {} 31 | 32 | #[debug_job] 33 | async fn job_with_qualified_self(self: Box) {} 34 | } 35 | 36 | fn main() {} 37 | -------------------------------------------------------------------------------- /crates/testing-utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-testing-utils" 3 | version = "0.1.0-alpha.20" 4 | description = "Testing utilities metapackage for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core-testing-utils = { workspace = true } 17 | blueprint-anvil-testing-utils = { workspace = true, optional = true } 18 | blueprint-tangle-testing-utils = { workspace = true, optional = true } 19 | blueprint-eigenlayer-testing-utils = { workspace = true, optional = true } 20 | 21 | [features] 22 | default = [] 23 | anvil = ["blueprint-anvil-testing-utils"] 24 | tangle = ["blueprint-tangle-testing-utils"] 25 | eigenlayer = ["blueprint-eigenlayer-testing-utils"] 26 | -------------------------------------------------------------------------------- /crates/clients/evm/src/client.rs: -------------------------------------------------------------------------------- 1 | //! Re-exported from 2 | 3 | use alloy_primitives::BlockNumber; 4 | use alloy_rpc_types::{Block, BlockNumberOrTag}; 5 | 6 | #[derive(Debug)] 7 | pub struct Client {} 8 | 9 | pub trait BackendClient { 10 | type Error; 11 | 12 | /// Get the latest block number. 13 | /// 14 | /// # Returns 15 | /// 16 | /// The latest block number. 17 | async fn block_number(&self) -> Result; 18 | 19 | /// Get the block hash given its block number. 20 | /// 21 | /// # Arguments 22 | /// 23 | /// * `number` - The block number. 24 | /// 25 | /// # Returns 26 | /// 27 | /// The block having that number. 28 | async fn block_by_number(&self, number: BlockNumberOrTag) 29 | -> Result, Self::Error>; 30 | } 31 | -------------------------------------------------------------------------------- /crates/testing-utils/core/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_runner::error::RunnerError; 2 | use thiserror::Error; 3 | 4 | #[derive(Error, Debug)] 5 | pub enum TestRunnerError { 6 | #[error(transparent)] 7 | Client(#[from] blueprint_clients::Error), 8 | #[error("Runner setup failed: {0}")] 9 | Setup(String), 10 | #[error("Runner execution failed: {0}")] 11 | Execution(String), 12 | #[error(transparent)] 13 | Io(#[from] std::io::Error), 14 | #[error(transparent)] 15 | Keystore(#[from] blueprint_keystore::Error), 16 | #[error(transparent)] 17 | Parse(#[from] url::ParseError), 18 | #[error(transparent)] 19 | Runner(#[from] RunnerError), 20 | #[error("Failed to wait for response: {0}")] 21 | WaitResponse(String), 22 | #[error(transparent)] 23 | Auth(#[from] blueprint_auth::Error), 24 | #[error(transparent)] 25 | Bridge(#[from] blueprint_manager_bridge::Error), 26 | } 27 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/soldeer.lock: -------------------------------------------------------------------------------- 1 | [[dependencies]] 2 | name = "@openzeppelin-contracts" 3 | version = "4.7.0" 4 | url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/4_7_0_22-01-2024_13:13:32_contracts.zip" 5 | checksum = "dfcc7462e91029c10321784588bbd694db54320979a75eb98f52f59de51f09aa" 6 | integrity = "aa86dfb5e769bb48d1c95e6e940f683161aa1081dbc0bb7421f340d0bda1eafe" 7 | 8 | [[dependencies]] 9 | name = "eigenlayer-middleware" 10 | version = "1.3.1" 11 | git = "https://github.com/Layr-Labs/eigenlayer-middleware" 12 | rev = "fd26169c7f988a53ad9ca1e745f40754afed4ed4" 13 | 14 | [[dependencies]] 15 | name = "forge-std" 16 | version = "1.9.6" 17 | url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/1_9_6_01-02-2025_20:49:10_forge-std-1.9.zip" 18 | checksum = "55f341818321b3f925161a72fd0dcd62e4a0a4b66785a7a932bf2bfaf96fb9d1" 19 | integrity = "e9ecdc364d152157431e5df5aa041ffddbe9bb1c1ad81634b1e72df9e23814e8" 20 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/wrong_return_type.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `bool: IntoJobResult` is not satisfied 2 | --> tests/debug_job/fail/wrong_return_type.rs:4:19 3 | | 4 | 4 | async fn job() -> bool { 5 | | ^^^^ the trait `IntoJobResult` is not implemented for `bool` 6 | | 7 | = help: the following other types implement trait `IntoJobResult`: 8 | &'static [u8; N] 9 | &'static [u8] 10 | &'static str 11 | () 12 | (JobResult<()>, R) 13 | (JobResult<()>, T1, R) 14 | (JobResult<()>, T1, T2, R) 15 | (JobResult<()>, T1, T2, T3, R) 16 | and $N others 17 | note: required by a bound in `__blueprint_macros_check_job_into_job_result::{closure#0}::check` 18 | --> tests/debug_job/fail/wrong_return_type.rs:4:19 19 | | 20 | 4 | async fn job() -> bool { 21 | | ^^^^ required by this bound in `check` 22 | -------------------------------------------------------------------------------- /.github/workflows/build-setup.yml: -------------------------------------------------------------------------------- 1 | # This file is used to install the Foundry toolchain and verify the installation. 2 | 3 | - name: Install Foundry 4 | uses: foundry-rs/foundry-toolchain@v1 5 | 6 | - name: Verify Forge installation 7 | run: | 8 | forge --version 9 | echo "Forge version check completed" 10 | 11 | - name: Install Solidity Dependencies 12 | run: | 13 | forge soldeer update -d 14 | echo "Solidity dependencies installed" 15 | 16 | - name: install protobuf and gmp (Linux) 17 | if: runner.os == 'Linux' 18 | run: | 19 | sudo apt-get update 20 | sudo apt-get install -y protobuf-compiler libprotobuf-dev libgmp-dev 21 | 22 | - name: install protobuf and gmp (macOS) 23 | if: runner.os == 'macOS' 24 | run: | 25 | brew install protobuf gmp 26 | echo "Installed protobuf and gmp on macOS" 27 | 28 | - name: Install LLVM and Clang 29 | uses: KyleMayes/install-llvm-action@v2 30 | with: 31 | version: "19.1.7" 32 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/not_send.stderr: -------------------------------------------------------------------------------- 1 | error: future cannot be sent between threads safely 2 | --> tests/debug_job/fail/not_send.rs:3:1 3 | | 4 | 3 | #[debug_job] 5 | | ^^^^^^^^^^^^ future returned by `job` is not `Send` 6 | | 7 | = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` 8 | note: future is not `Send` as this value is used across an await 9 | --> tests/debug_job/fail/not_send.rs:6:14 10 | | 11 | 5 | let _rc = std::rc::Rc::new(()); 12 | | --- has type `Rc<()>` which is not `Send` 13 | 6 | async {}.await; 14 | | ^^^^^ await occurs here, with `_rc` maybe used later 15 | note: required by a bound in `check` 16 | --> tests/debug_job/fail/not_send.rs:3:1 17 | | 18 | 3 | #[debug_job] 19 | | ^^^^^^^^^^^^ required by this bound in `check` 20 | = note: this error originates in the attribute macro `debug_job` (in Nightly builds, run with -Z macro-backtrace for more info) 21 | -------------------------------------------------------------------------------- /crates/evm-extra/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! EVM Job Utilities 2 | //! 3 | //! This crate provides utilities for working with EVM-based job processing in the Blueprint framework. 4 | //! It includes functionality for event extraction, block processing, finality determination, 5 | //! and contract interaction. 6 | //! 7 | //! ## Features 8 | #![doc = document_features::document_features!()] 9 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 10 | #![doc( 11 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 12 | )] 13 | #![deny( 14 | missing_debug_implementations, 15 | missing_copy_implementations, 16 | trivial_casts, 17 | trivial_numeric_casts, 18 | unsafe_code, 19 | unstable_features, 20 | unused_import_braces, 21 | unused_qualifications 22 | )] 23 | 24 | extern crate alloc; 25 | 26 | pub mod consumer; 27 | pub mod extract; 28 | pub mod filters; 29 | pub mod producer; 30 | pub mod util; 31 | -------------------------------------------------------------------------------- /crates/testing-utils/anvil/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-anvil-testing-utils" 3 | version = "0.1.0-alpha.21" 4 | description = "Anvil testing utilities for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core = { workspace = true, features = ["tracing"] } 17 | blueprint-std = { workspace = true } 18 | tokio = { workspace = true } 19 | blueprint-core-testing-utils = { workspace = true } 20 | 21 | alloy-primitives = { workspace = true } 22 | alloy-provider = { workspace = true } 23 | alloy-rpc-types = { workspace = true } 24 | alloy-rpc-types-eth = { workspace = true } 25 | alloy-transport = { workspace = true } 26 | url = { workspace = true } 27 | 28 | [features] 29 | default = ["tracing"] 30 | tracing = ["blueprint-core/tracing"] 31 | -------------------------------------------------------------------------------- /crates/metrics/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-metrics-v0.1.0-alpha.2...blueprint-metrics-v0.1.0-alpha.3) - 2025-05-01 11 | 12 | ### Other 13 | 14 | - remove unused dependencies (#915) 15 | 16 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-metrics-v0.1.0-alpha.1...blueprint-metrics-v0.1.0-alpha.2) - 2025-04-21 17 | 18 | ### Other 19 | 20 | - updated the following local packages: blueprint-metrics-rpc-calls 21 | 22 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-metrics-v0.1.0-alpha.1) - 2025-04-08 23 | 24 | ### Other 25 | 26 | - Initial release 27 | -------------------------------------------------------------------------------- /crates/chain-setup/anvil/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error("Error occurred in Testnet: {0}")] 4 | Container(String), 5 | #[error("Failed to mine anvil blocks: {0}")] 6 | Mine(String), 7 | #[error("Error occurred while waiting for responses: {0}")] 8 | WaitResponse(String), 9 | #[error("Contract Error: {0}")] 10 | Contract(#[from] alloy_contract::Error), 11 | #[error("Transaction Error: {0}")] 12 | Transaction(#[from] alloy_provider::PendingTransactionError), 13 | #[error("Keystore error: {0}")] 14 | Keystore(#[from] Box), 15 | } 16 | 17 | impl From for Error { 18 | fn from(e: tokio::time::error::Elapsed) -> Self { 19 | Error::WaitResponse(e.to_string()) 20 | } 21 | } 22 | 23 | impl From for Error { 24 | fn from(e: blueprint_keystore::Error) -> Self { 25 | Box::new(e).into() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/apikey-blueprint-lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "apikey-blueprint-lib" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | axum = { version = "0.8", default-features = false, features = ["http2", "json", "tokio"] } 8 | blueprint-sdk = { path = "../../../crates/sdk", default-features = false, features = [ 9 | "std", 10 | "tracing", 11 | "macros", 12 | "tangle", 13 | ] } 14 | serde = { version = "1", features = ["derive"] } 15 | serde_json = { version = "1" } 16 | tokio = { version = "^1", default-features = false, features = ["rt", "macros"] } 17 | tower = { version = "0.5.2", default-features = false } 18 | sha2 = "0.10" 19 | uuid = { version = "1.0", features = ["v4", "serde"] } 20 | 21 | [dev-dependencies] 22 | blueprint-sdk = { path = "../../../crates/sdk", features = ["testing", "tangle"] } 23 | blueprint-tangle-extra = { path = "../../../crates/tangle-extra" } 24 | tokio = { version = "^1", features = ["macros"] } 25 | color-eyre = "0.6" 26 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/settings.env: -------------------------------------------------------------------------------- 1 | REGISTRY_COORDINATOR_ADDRESS=b7278a61aa25c888815afc32ad3cc52ff24fe575 2 | OPERATOR_STATE_RETRIEVER_ADDRESS=1429859428c0abc9c2c47c8ee9fbaf82cfa0f20f 3 | DELEGATION_MANAGER_ADDRESS=9fe46736679d2d9a65f0992f2272de9f3c7fa6e0 4 | STRATEGY_MANAGER_ADDRESS=0165878a594ca255338adfa4d48449f69242eb8f 5 | STRATEGY_ADDRESS=8e80ffe6dc044f4a766afd6e5a8732fe0977a493 6 | STAKE_REGISTRY_ADDRESS=809d550fca64d94bd9f66e60752a544199cfac3d 7 | AVS_DIRECTORY_ADDRESS=dc64a140aa3e981100a9beca4e685f962f0cf6c9 8 | REWARDS_COORDINATOR_ADDRESS=610178da211fef7d417bc0e6fed39f05609ad788 9 | PERMISSION_CONTROLLER_ADDRESS=68b1d87f95878fe05b998f19b66f4baba5de1aed 10 | PAUSE_REGISTRY_ADDRESS=3aa5ebb10dc797cac828524e59a333d0a371443c 11 | ALLOCATION_MANAGER_ADDRESS=2279b7a0a67db372996a5fab50d91eaa73d2ebe6 12 | SLASHER_ADDRESS=cbeaf3bde82155f56486fb5a1072cb8baaf547cc 13 | TASK_MANAGER_ADDRESS=1291be112d480055dafd8a610b7d1e203891c274 14 | SERVICE_MANAGER_ADDRESS=5eb3bc0a489c5a8288765d2336659ebca68fcd00 -------------------------------------------------------------------------------- /crates/metrics/rpc-calls/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-metrics-rpc-calls-v0.1.0-alpha.2...blueprint-metrics-rpc-calls-v0.1.0-alpha.3) - 2025-05-01 11 | 12 | ### Other 13 | 14 | - remove unused dependencies (#915) 15 | 16 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-metrics-rpc-calls-v0.1.0-alpha.1...blueprint-metrics-rpc-calls-v0.1.0-alpha.2) - 2025-04-21 17 | 18 | ### Other 19 | 20 | - update Cargo.toml dependencies 21 | 22 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-metrics-rpc-calls-v0.1.0-alpha.1) - 2025-04-08 23 | 24 | ### Other 25 | 26 | - Initial release 27 | -------------------------------------------------------------------------------- /crates/crypto/ed25519/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-ed25519" 3 | version = "0.1.0-alpha.10" 4 | description = "Zebra ed25519 crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-crypto-core = { workspace = true, features = ["zebra"] } 14 | blueprint-std = { workspace = true } 15 | ed25519-zebra = { workspace = true } 16 | serde = { workspace = true } 17 | serde_bytes = { workspace = true, features = ["alloc"] } 18 | hex = { workspace = true } 19 | thiserror = { workspace = true } 20 | 21 | [dev-dependencies] 22 | serde_json = { workspace = true, features = ["alloc"] } 23 | 24 | [features] 25 | default = ["std"] 26 | std = [ 27 | "blueprint-crypto-core/std", 28 | "blueprint-std/std", 29 | "serde/std", 30 | "serde_json/std", 31 | "serde_bytes/std", 32 | "ed25519-zebra/std", 33 | ] 34 | -------------------------------------------------------------------------------- /crates/clients/core/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(thiserror::Error, Debug)] 2 | pub enum Error { 3 | #[error("Eigenlayer error: `{0}`")] 4 | Eigenlayer(String), 5 | #[error("EVM error: `{0}`")] 6 | Evm(String), 7 | #[error("Tangle error: `{0}`")] 8 | Tangle(String), 9 | #[error("Network error: `{0}`")] 10 | Network(String), 11 | #[error("Unable to fetch operators: `{0}`")] 12 | GetOperators(String), 13 | #[error("Unable to fetch operator id: `{0}`")] 14 | OperatorId(String), 15 | #[error("Unable to fetch unique id: `{0}`")] 16 | UniqueId(String), 17 | #[error("Unable to fetch operators and operator id: `{0}`")] 18 | GetOperatorsAndOperatorId(String), 19 | #[error("Unable to fetch operator index: `{0}`")] 20 | GetOperatorIndex(String), 21 | #[error("Client error: `{0}`")] 22 | Other(String), 23 | } 24 | 25 | impl Error { 26 | pub fn msg(msg: T) -> Self { 27 | Error::Other(format!("{msg:?}")) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/oauth-blueprint/oauth-blueprint-lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "oauth-blueprint-lib" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | axum = { version = "0.8", default-features = false, features = ["http2", "json", "tokio"] } 8 | blueprint-sdk = { path = "../../../crates/sdk", default-features = false, features = ["std", "tracing", "macros", "tangle"] } 9 | serde = { version = "1", features = ["derive"] } 10 | serde_json = { version = "1" } 11 | tokio = { version = "^1", default-features = false, features = ["rt", "macros"] } 12 | tower = { version = "0.5.2", default-features = false } 13 | uuid = { version = "1.0", features = ["v4", "serde"] } 14 | 15 | [dev-dependencies] 16 | blueprint-sdk = { path = "../../../crates/sdk", features = ["testing", "tangle"] } 17 | blueprint-tangle-extra = { path = "../../../crates/tangle-extra" } 18 | blueprint-testing-utils = { path = "../../../crates/testing-utils" } 19 | tempfile = "3.0" 20 | tokio = { version = "^1", features = ["macros"] } 21 | color-eyre = "0.6" 22 | -------------------------------------------------------------------------------- /crates/chain-setup/anvil/src/state.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::HashMap; 3 | 4 | #[derive(Debug, Serialize, Deserialize)] 5 | pub struct AnvilState { 6 | pub accounts: HashMap, 7 | } 8 | 9 | #[derive(Debug, Serialize, Deserialize)] 10 | pub struct AccountState { 11 | pub nonce: u64, 12 | pub balance: String, 13 | pub code: String, 14 | pub storage: HashMap, 15 | } 16 | 17 | /// Get the default Anvil state as a raw JSON string 18 | #[must_use] 19 | pub fn get_default_state_json() -> &'static str { 20 | DEFAULT_STATE 21 | } 22 | 23 | /// Get the default Anvil state parsed into the [`AnvilState`] struct 24 | #[must_use] 25 | #[allow(clippy::missing_panics_doc)] 26 | pub fn get_default_state() -> AnvilState { 27 | serde_json::from_str(DEFAULT_STATE).expect("Failed to parse default state JSON") 28 | } 29 | 30 | // The default state JSON data - stored like this for simplicity 31 | const DEFAULT_STATE: &str = include_str!("../data/state.json"); 32 | -------------------------------------------------------------------------------- /crates/crypto/sr25519/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-sr25519" 3 | version = "0.1.0-alpha.10" 4 | description = "Schnorrkel sr25519 crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-crypto-core = { workspace = true, features = ["sr25519-schnorrkel"] } 14 | blueprint-std = { workspace = true } 15 | schnorrkel = { workspace = true } 16 | serde = { workspace = true } 17 | serde_bytes = { workspace = true, features = ["alloc"] } 18 | hex = { workspace = true, features = ["alloc"] } 19 | thiserror = { workspace = true } 20 | 21 | [dev-dependencies] 22 | serde_json = { workspace = true, features = ["alloc"] } 23 | 24 | [features] 25 | default = ["std"] 26 | std = [ 27 | "blueprint-crypto-core/std", 28 | "blueprint-std/std", 29 | "serde/std", 30 | "serde_json/std", 31 | "serde_bytes/std", 32 | "schnorrkel/std", 33 | ] 34 | -------------------------------------------------------------------------------- /crates/crypto/ed25519/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_std::string::String; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Clone, Error)] 5 | pub enum Ed25519Error { 6 | #[error("Invalid seed: {0}")] 7 | InvalidSeed(String), 8 | #[error("Invalid public key: {0}")] 9 | InvalidVerifyingKey(String), 10 | #[error("Invalid signing key: {0}")] 11 | InvalidSigner(String), 12 | #[error("Invalid signature: {0}")] 13 | InvalidSignature(String), 14 | #[error("Zebra error: {0}")] 15 | ZebraError(ed25519_zebra::Error), 16 | #[error("Invalid hex string: {0}")] 17 | HexError(hex::FromHexError), 18 | } 19 | 20 | impl From for Ed25519Error { 21 | fn from(error: ed25519_zebra::Error) -> Self { 22 | Ed25519Error::ZebraError(error) 23 | } 24 | } 25 | 26 | impl From for Ed25519Error { 27 | fn from(error: hex::FromHexError) -> Self { 28 | Ed25519Error::HexError(error) 29 | } 30 | } 31 | 32 | pub type Result = blueprint_std::result::Result; 33 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/single_wrong_return_tuple.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `NotIntoJobResult: IntoJobResult` is not satisfied 2 | --> tests/debug_job/fail/single_wrong_return_tuple.rs:6:19 3 | | 4 | 6 | async fn job() -> (NotIntoJobResult) { 5 | | ^^^^^^^^^^^^^^^^^^ the trait `IntoJobResult` is not implemented for `NotIntoJobResult` 6 | | 7 | = help: the following other types implement trait `IntoJobResult`: 8 | &'static [u8; N] 9 | &'static [u8] 10 | &'static str 11 | () 12 | (JobResult<()>, R) 13 | (JobResult<()>, T1, R) 14 | (JobResult<()>, T1, T2, R) 15 | (JobResult<()>, T1, T2, T3, R) 16 | and $N others 17 | note: required by a bound in `__blueprint_macros_check_job_into_job_result::{closure#0}::check` 18 | --> tests/debug_job/fail/single_wrong_return_tuple.rs:6:19 19 | | 20 | 6 | async fn job() -> (NotIntoJobResult) { 21 | | ^^^^^^^^^^^^^^^^^^ required by this bound in `check` 22 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/avs_contracts.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxy_admin": "0x8f86403a4de0bb5791fa46b8e795c547942fe4cf", 3 | "squaring_service_manager": "0x5eb3bc0a489c5a8288765d2336659ebca68fcd00", 4 | "squaring_service_manager_impl": "0x51a1ceb83b83f1985a81c295d1ff28afef186e02", 5 | "squaring_task_manager": "0x1291be112d480055dafd8a610b7d1e203891c274", 6 | "registry_coordinator": "0xb7278a61aa25c888815afc32ad3cc52ff24fe575", 7 | "bls_apk_registry": "0x82e01223d51eb87e16a03e24687edf0f294da6f1", 8 | "index_registry": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", 9 | "stake_registry": "0x809d550fca64d94bd9f66e60752a544199cfac3d", 10 | "operator_state_retriever": "0x1429859428c0abc9c2c47c8ee9fbaf82cfa0f20f", 11 | "strategy": "0x8e80ffe6dc044f4a766afd6e5a8732fe0977a493", 12 | "pauser_registry": "0x4c4a2f8c81640e47606d3fd77b353e87ba015584", 13 | "token": "0x70e0ba845a1a0f2da3359c97e0285013525ffc49", 14 | "instant_slasher": "0xcbeaf3bde82155f56486fb5a1072cb8baaf547cc", 15 | "socket_registry": "0xc351628eb244ec633d5f21fbd6621e1a683b1181" 16 | } -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/src/contexts/combined.rs: -------------------------------------------------------------------------------- 1 | use crate::contexts::aggregator::AggregatorContext; 2 | use crate::contexts::x_square::EigenSquareContext; 3 | use blueprint_sdk::macros::context::KeystoreContext; 4 | use blueprint_sdk::runner::config::BlueprintEnvironment; 5 | 6 | /// Combined context that includes both the EigenSquareContext and AggregatorContext 7 | /// This allows both jobs to share the same context in the router 8 | #[derive(Clone, KeystoreContext)] 9 | pub struct CombinedContext { 10 | pub eigen_context: EigenSquareContext, 11 | pub aggregator_context: Option, 12 | #[config] 13 | pub std_config: BlueprintEnvironment, 14 | } 15 | 16 | impl CombinedContext { 17 | pub fn new( 18 | eigen_context: EigenSquareContext, 19 | aggregator_context: Option, 20 | std_config: BlueprintEnvironment, 21 | ) -> Self { 22 | Self { 23 | eigen_context, 24 | aggregator_context, 25 | std_config, 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/router/src/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate std; 2 | 3 | use crate::Router; 4 | use crate::test_helpers::setup_log; 5 | use blueprint_core::error::BoxError; 6 | use blueprint_core::job::call::JobCall; 7 | use bytes::Bytes; 8 | use tower::Service; 9 | 10 | #[tokio::test] 11 | async fn fallible_job() { 12 | setup_log(); 13 | 14 | async fn job_ok() -> Result<(), BoxError> { 15 | Ok(()) 16 | } 17 | 18 | async fn job_err() -> Result<(), BoxError> { 19 | Err("error".into()) 20 | } 21 | 22 | let mut router: Router = Router::new().route(0, job_ok).route(1, job_err); 23 | 24 | let Some(res) = router.call(JobCall::new(0, Bytes::new())).await.unwrap() else { 25 | panic!("job should produce a result"); 26 | }; 27 | 28 | std::assert_eq!(res.len(), 1); 29 | std::assert!(res[0].is_ok()); 30 | 31 | let Some(res) = router.call(JobCall::new(1, Bytes::new())).await.unwrap() else { 32 | panic!("job should produce a result"); 33 | }; 34 | 35 | std::assert_eq!(res.len(), 1); 36 | std::assert!(res[0].is_err()); 37 | } 38 | -------------------------------------------------------------------------------- /crates/testing-utils/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-core-testing-utils" 3 | version = "0.1.0-alpha.21" 4 | description = "Core primitives for testing Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core = { workspace = true } 17 | blueprint-runner = { workspace = true } 18 | blueprint-router = { workspace = true } 19 | blueprint-qos = { workspace = true, features = ["std"] } 20 | blueprint-auth = { workspace = true, features = ["std"] } 21 | blueprint-clients = { workspace = true, features = ["std"] } 22 | blueprint-keystore = { workspace = true, features = ["std"] } 23 | blueprint-manager-bridge.workspace = true 24 | 25 | cargo_toml = { workspace = true } 26 | thiserror = { workspace = true } 27 | tokio = { workspace = true } 28 | url = { workspace = true } 29 | tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] } 30 | -------------------------------------------------------------------------------- /crates/eigenlayer-extra/example-avs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "service_manager": "0x0000000000000000000000000000000000000000", 3 | "registry_coordinator": "0x0000000000000000000000000000000000000000", 4 | "operator_state_retriever": "0x0000000000000000000000000000000000000000", 5 | "strategy_manager": "0x0000000000000000000000000000000000000000", 6 | "delegation_manager": "0x0000000000000000000000000000000000000000", 7 | "avs_directory": "0x0000000000000000000000000000000000000000", 8 | "rewards_coordinator": "0x0000000000000000000000000000000000000000", 9 | "permission_controller": "0x0000000000000000000000000000000000000000", 10 | "allocation_manager": "0x0000000000000000000000000000000000000000", 11 | "strategy_address": "0x0000000000000000000000000000000000000000", 12 | "stake_registry": "0x0000000000000000000000000000000000000000", 13 | "blueprint_path": "/path/to/your/avs/blueprint", 14 | "runtime_target": "hypervisor", 15 | "allocation_delay": 0, 16 | "deposit_amount": 5000000000000000000000, 17 | "stake_amount": 1000000000000000000, 18 | "operator_sets": [0] 19 | } 20 | -------------------------------------------------------------------------------- /crates/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-core" 3 | version = "0.1.0-alpha.5" 4 | description = "Blueprint SDK Core functionality" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | bytes.workspace = true 14 | futures-util.workspace = true 15 | pin-project-lite.workspace = true 16 | tower = { workspace = true, features = ["util"] } 17 | hashbrown = { workspace = true, default-features = false, features = ["default-hasher", "inline-more"] } 18 | tiny-keccak = { workspace = true, features = ["keccak"] } 19 | tracing = { workspace = true } 20 | 21 | [dev-dependencies] 22 | blueprint-sdk = { path = "../sdk", features = ["std"] } 23 | serde_json = { workspace = true, features = ["alloc"] } 24 | tower = { workspace = true, features = ["util", "timeout", "limit", "load-shed", "steer", "filter"] } 25 | tokio = { workspace = true, features = ["full"] } 26 | 27 | [features] 28 | default = ["std", "tracing"] 29 | std = ["futures-util/std"] 30 | tracing = [] 31 | -------------------------------------------------------------------------------- /crates/macros/context-derive/src/keystore.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | use syn::DeriveInput; 3 | 4 | use crate::cfg::FieldInfo; 5 | 6 | /// Generate the `KeystoreContext` implementation for the given struct. 7 | pub fn generate_context_impl( 8 | DeriveInput { 9 | ident: name, 10 | generics, 11 | .. 12 | }: DeriveInput, 13 | config_field: FieldInfo, 14 | ) -> proc_macro2::TokenStream { 15 | let field_access = match config_field { 16 | FieldInfo::Named(ident) => quote! { self.#ident }, 17 | FieldInfo::Unnamed(index) => quote! { self.#index }, 18 | }; 19 | 20 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 21 | 22 | quote! { 23 | impl #impl_generics ::blueprint_sdk::contexts::keystore::KeystoreContext for #name #ty_generics #where_clause { 24 | fn keystore(&self) -> ::blueprint_sdk::keystore::Keystore { 25 | <::blueprint_sdk::runner::config::BlueprintEnvironment as ::blueprint_sdk::contexts::keystore::KeystoreContext>::keystore(&#field_access) 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /crates/qos/src/servers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | pub mod grafana; 3 | pub mod loki; 4 | pub mod prometheus; 5 | 6 | use crate::error::Result; 7 | 8 | /// Common trait for server management 9 | pub trait ServerManager: Send + Sync { 10 | /// Start the server 11 | /// 12 | /// # Errors 13 | /// Returns an error if the server fails to start 14 | async fn start(&self, network: Option<&str>, bind_ip: Option) -> Result<()>; 15 | 16 | /// Stop the server 17 | /// 18 | /// # Errors 19 | /// Returns an error if the server fails to stop 20 | async fn stop(&self) -> Result<()>; 21 | 22 | /// Get the URL of the server 23 | fn url(&self) -> String; 24 | 25 | /// Check if the server is running 26 | /// 27 | /// # Errors 28 | /// Returns an error if the check fails 29 | async fn is_running(&self) -> Result; 30 | 31 | /// Wait for the server to be ready 32 | /// 33 | /// # Errors 34 | /// Returns an error if the server fails to become ready within the timeout 35 | async fn wait_until_ready(&self, timeout_secs: u64) -> Result<()>; 36 | } 37 | -------------------------------------------------------------------------------- /crates/crypto/k256/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-k256" 3 | version = "0.1.0-alpha.10" 4 | description = "k256 crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-crypto-core = { workspace = true, features = ["k256"] } 14 | blueprint-std = { workspace = true } 15 | k256 = { workspace = true, features = ["ecdsa", "alloc", "serde", "pem"] } 16 | serde = { workspace = true } 17 | serde_bytes = { workspace = true, features = ["alloc"] } 18 | thiserror = { workspace = true } 19 | hex = { workspace = true, features = ["alloc"] } 20 | alloy-signer-local = { workspace = true } 21 | alloy-primitives = { workspace = true } 22 | 23 | [dev-dependencies] 24 | serde_json = { workspace = true, features = ["alloc"] } 25 | 26 | [features] 27 | default = ["std"] 28 | std = [ 29 | "blueprint-crypto-core/std", 30 | "blueprint-std/std", 31 | "serde/std", 32 | "serde_json/std", 33 | "serde_bytes/std", 34 | "k256/std", 35 | ] 36 | -------------------------------------------------------------------------------- /crates/manager/src/rt/native.rs: -------------------------------------------------------------------------------- 1 | use super::service::Status; 2 | use tokio::sync::mpsc::UnboundedReceiver; 3 | 4 | /// Handle for a natively (no sandbox) running service 5 | pub struct ProcessHandle { 6 | status: UnboundedReceiver, 7 | cached_status: Status, 8 | abort_handle: tokio::sync::oneshot::Sender<()>, 9 | } 10 | 11 | impl ProcessHandle { 12 | #[must_use] 13 | pub fn new( 14 | mut status: UnboundedReceiver, 15 | abort_handle: tokio::sync::oneshot::Sender<()>, 16 | ) -> Self { 17 | let cached_status = status.try_recv().ok().unwrap_or(Status::Running); 18 | Self { 19 | status, 20 | cached_status, 21 | abort_handle, 22 | } 23 | } 24 | 25 | pub fn status(&mut self) -> Status { 26 | self.status.try_recv().ok().unwrap_or(self.cached_status) 27 | } 28 | 29 | pub async fn wait_for_status_change(&mut self) -> Option { 30 | self.status.recv().await 31 | } 32 | 33 | #[must_use] 34 | pub fn abort(self) -> bool { 35 | self.abort_handle.send(()).is_ok() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/clients/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-clients" 3 | version = "0.1.0-alpha.21" 4 | description = "Metapackage for Tangle Blueprint clients" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-client-eigenlayer = { workspace = true, optional = true } 17 | blueprint-client-evm = { workspace = true, optional = true } 18 | blueprint-client-tangle = { workspace = true, optional = true } 19 | blueprint-client-core = { workspace = true } 20 | blueprint-std.workspace = true 21 | 22 | thiserror.workspace = true 23 | 24 | [features] 25 | default = ["std"] 26 | std = [ 27 | "blueprint-client-eigenlayer?/std", 28 | "blueprint-client-evm?/std", 29 | "blueprint-client-tangle?/std", 30 | "blueprint-std/std", 31 | "thiserror/std", 32 | ] 33 | web = ["blueprint-client-tangle?/web"] 34 | 35 | eigenlayer = ["dep:blueprint-client-eigenlayer"] 36 | evm = ["dep:blueprint-client-evm"] 37 | tangle = ["dep:blueprint-client-tangle"] 38 | -------------------------------------------------------------------------------- /crates/core/src/error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | 3 | /// Alias for a type-erased error type. 4 | pub type BoxError = alloc::boxed::Box; 5 | pub type CloneableError = alloc::sync::Arc; 6 | 7 | /// Errors that can happen when using `blueprint-sdk` job routing. 8 | #[derive(Debug, Clone)] 9 | pub struct Error { 10 | inner: CloneableError, 11 | } 12 | 13 | impl Error { 14 | /// Create a new `Error` from a boxable error. 15 | pub fn new(error: impl Into) -> Self { 16 | Self { 17 | inner: CloneableError::from(error.into()), 18 | } 19 | } 20 | 21 | /// Convert an `Error` back into the underlying trait object. 22 | pub fn into_inner(self) -> CloneableError { 23 | self.inner 24 | } 25 | } 26 | 27 | impl fmt::Display for Error { 28 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 29 | self.inner.fmt(f) 30 | } 31 | } 32 | 33 | impl core::error::Error for Error { 34 | fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { 35 | Some(&*self.inner) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/eigenlayer-extra/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error as ThisError; 2 | 3 | #[derive(ThisError, Debug)] 4 | #[allow(clippy::large_enum_variant)] 5 | pub enum EigenlayerExtraError { 6 | #[error("Keystore error: {0}")] 7 | Keystore(#[from] blueprint_keystore::Error), 8 | 9 | #[error("Contract interaction failed: {0}")] 10 | Contract(String), 11 | 12 | #[error("Transaction failed: {0}")] 13 | Transaction(String), 14 | 15 | #[error("Operator not registered")] 16 | OperatorNotRegistered, 17 | 18 | #[error("No rewards available to claim")] 19 | NoRewardsAvailable, 20 | 21 | #[error("Operator is slashed")] 22 | OperatorSlashed, 23 | 24 | #[error("Invalid configuration: {0}")] 25 | InvalidConfiguration(String), 26 | 27 | #[error("EigenSDK error: {0}")] 28 | EigenSdk(String), 29 | 30 | #[error("Provider error: {0}")] 31 | Provider(String), 32 | 33 | #[error("Other error: {0}")] 34 | Other(String), 35 | } 36 | 37 | /// Type alias for convenience 38 | pub type Error = EigenlayerExtraError; 39 | 40 | pub type Result = std::result::Result; 41 | -------------------------------------------------------------------------------- /crates/qos/config/loki-config.yaml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | 3 | server: 4 | http_listen_port: 3100 5 | 6 | ingester: 7 | lifecycler: 8 | address: 127.0.0.1 9 | ring: 10 | kvstore: 11 | store: inmemory 12 | replication_factor: 1 13 | final_sleep: 0s 14 | chunk_idle_period: 1m 15 | chunk_retain_period: 30s 16 | wal: 17 | enabled: true 18 | dir: /loki/wal 19 | 20 | 21 | schema_config: 22 | configs: 23 | - from: 2020-10-24 24 | store: boltdb-shipper 25 | object_store: filesystem 26 | schema: v11 27 | index: 28 | prefix: index_ 29 | period: 24h 30 | 31 | storage_config: 32 | boltdb_shipper: 33 | active_index_directory: /loki/index 34 | cache_location: /loki/cache 35 | cache_ttl: 24h 36 | 37 | filesystem: 38 | directory: /loki/chunks 39 | 40 | compactor: 41 | working_directory: /loki/compactor 42 | 43 | limits_config: 44 | reject_old_samples: true 45 | reject_old_samples_max_age: 168h 46 | allow_structured_metadata: false 47 | 48 | 49 | 50 | table_manager: 51 | retention_deletes_enabled: false 52 | retention_period: 0s 53 | -------------------------------------------------------------------------------- /crates/std/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-std-v0.1.0-alpha.3...blueprint-std-v0.1.0-alpha.4) - 2025-10-07 11 | 12 | ### Other 13 | 14 | - update Cargo.toml dependencies 15 | 16 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-std-v0.1.0-alpha.2...blueprint-std-v0.1.0-alpha.3) - 2025-05-09 17 | 18 | ### Other 19 | 20 | - remove gadget references (#967) 21 | 22 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-std-v0.1.0-alpha.1...blueprint-std-v0.1.0-alpha.2) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - remove unused dependencies (#915) 27 | 28 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-std-v0.1.0-alpha.1) - 2025-04-08 29 | 30 | ### Other 31 | 32 | - Initial release 33 | -------------------------------------------------------------------------------- /crates/crypto/hashing/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "sha2")] 2 | pub fn sha2_256(data: &[u8]) -> [u8; 32] { 3 | use sha2::Digest; 4 | 5 | let mut hasher = sha2::Sha256::new(); 6 | hasher.update(data); 7 | let result = hasher.finalize(); 8 | let mut hash = [0u8; 32]; 9 | hash.copy_from_slice(&result); 10 | hash 11 | } 12 | 13 | #[cfg(feature = "sha2")] 14 | pub fn sha2_512(data: &[u8]) -> [u8; 64] { 15 | use sha2::Digest; 16 | 17 | let mut hasher = sha2::Sha512::new(); 18 | hasher.update(data); 19 | let result = hasher.finalize(); 20 | let mut hash = [0u8; 64]; 21 | hash.copy_from_slice(&result); 22 | hash 23 | } 24 | 25 | #[cfg(feature = "sha3")] 26 | pub fn keccak_256(data: &[u8]) -> [u8; 32] { 27 | use sha3::Digest; 28 | 29 | let mut hasher = sha3::Keccak256::new(); 30 | hasher.update(data); 31 | let output = hasher.finalize(); 32 | output.into() 33 | } 34 | 35 | #[cfg(feature = "blake3")] 36 | pub fn blake3_256(data: &[u8]) -> [u8; 32] { 37 | let mut hasher = blake3::Hasher::new(); 38 | hasher.update(data); 39 | let output = hasher.finalize(); 40 | output.into() 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Tangle Network 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist-workspace.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["cargo:."] 3 | 4 | # Config for 'dist' 5 | [dist] 6 | # CI backends to support 7 | ci = "github" 8 | # Whether dist should create a Github Release or use an existing draft 9 | create-release = false 10 | github-build-setup = "build-setup.yml" 11 | # The installers to generate for each app 12 | installers = ["shell"] 13 | # Target platforms to build apps for (Rust target-triple syntax) 14 | targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"] 15 | # Path that installers should place binaries in 16 | install-path = "CARGO_HOME" 17 | # Whether to install an updater program 18 | install-updater = true 19 | bin-aliases = { cargo-tangle = ["tangle", "tg"] } 20 | members = ["cargo:/cli"] 21 | # Which actions to run on pull requests 22 | pr-run-mode = "plan" 23 | # The preferred dist version to use in CI (Cargo.toml SemVer syntax) 24 | cargo-dist-version = "0.28.7-prerelease.1" 25 | 26 | [dist.github-custom-runners] 27 | global = "ubuntu-latest" 28 | # Custom runners to use for each target platform 29 | aarch64-apple-darwin = "macos-15" 30 | x86_64-apple-darwin = "macos-13" 31 | x86_64-unknown-linux-gnu = "ubuntu-latest" 32 | -------------------------------------------------------------------------------- /crates/chain-setup/anvil/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-chain-setup-anvil" 3 | version = "0.1.0-alpha.21" 4 | description = "Anvil-specific chain setup utilities" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-std = { workspace = true } 14 | blueprint-keystore = { workspace = true, features = ["eigenlayer", "evm"] } 15 | blueprint-core-testing-utils = { workspace = true } 16 | blueprint-core = { workspace = true } 17 | alloy-contract = { workspace = true } 18 | alloy-provider = { workspace = true } 19 | alloy-rpc-types = { workspace = true } 20 | alloy-rpc-types-eth = { workspace = true } 21 | serde = { workspace = true } 22 | serde_json = { workspace = true, features = ["alloc"] } 23 | testcontainers = { workspace = true } 24 | thiserror = { workspace = true } 25 | tokio = { workspace = true } 26 | tempfile = { workspace = true} 27 | url.workspace = true 28 | 29 | 30 | [features] 31 | default = ["std"] 32 | std = [ 33 | "blueprint-std/std", 34 | "blueprint-keystore/std", 35 | "tokio/full", 36 | ] 37 | -------------------------------------------------------------------------------- /crates/clients/core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-client-core-v0.1.0-alpha.3...blueprint-client-core-v0.1.0-alpha.4) - 2025-10-07 11 | 12 | ### Other 13 | 14 | - update Cargo.toml dependencies 15 | 16 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-client-core-v0.1.0-alpha.2...blueprint-client-core-v0.1.0-alpha.3) - 2025-05-09 17 | 18 | ### Other 19 | 20 | - remove gadget references (#967) 21 | 22 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-client-core-v0.1.0-alpha.1...blueprint-client-core-v0.1.0-alpha.2) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - remove unused dependencies (#915) 27 | 28 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-client-core-v0.1.0-alpha.1) - 2025-04-08 29 | 30 | ### Other 31 | 32 | - Initial release 33 | -------------------------------------------------------------------------------- /.github/workflows/claude-review.yml: -------------------------------------------------------------------------------- 1 | name: Auto review PRs 2 | 3 | on: 4 | pull_request: 5 | types: [opened, ready_for_review] 6 | 7 | jobs: 8 | auto-review: 9 | if: github.event.pull_request.draft == false 10 | permissions: 11 | contents: read 12 | id-token: write 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 1 20 | 21 | - name: Auto review PR 22 | uses: anthropics/claude-code-action@v1 23 | with: 24 | prompt: | 25 | Review this PR like an expert, critical L7 engineering lead. Optimize token usage, high signal to noise: 26 | - Code quality and best practices match repo 27 | - Potential bugs or issues 28 | - Performance 29 | - Security implications 30 | - Missing documentation 31 | 32 | Be constructive and specific in your feedback. Give inline comments where applicable. 33 | claude_args: | 34 | --allowedTools "mcp__github__add_pull_request_review_comment" 35 | claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} -------------------------------------------------------------------------------- /crates/networking/src/discovery/mod.rs: -------------------------------------------------------------------------------- 1 | use std::{num::NonZero, time::Duration}; 2 | 3 | use libp2p::{ 4 | PeerId, StreamProtocol, 5 | kad::{self, store::MemoryStore}, 6 | }; 7 | 8 | pub mod behaviour; 9 | pub mod config; 10 | pub mod peers; 11 | pub mod utils; 12 | 13 | pub use peers::{PeerEvent, PeerInfo, PeerManager}; 14 | 15 | #[must_use] 16 | #[allow(clippy::missing_panics_doc)] 17 | pub fn new_kademlia(peer_id: PeerId, protocol: StreamProtocol) -> kad::Behaviour { 18 | let store = kad::store::MemoryStore::new(peer_id); 19 | let mut config = kad::Config::new(protocol); 20 | 21 | // Optimize Kademlia configuration 22 | config 23 | .set_query_timeout(Duration::from_secs(60)) 24 | .set_replication_factor(NonZero::new(3).unwrap()) 25 | .set_publication_interval(Some(Duration::from_secs(120))) 26 | .set_provider_record_ttl(Some(Duration::from_secs(24 * 60 * 60))) 27 | .set_record_ttl(Some(Duration::from_secs(24 * 60 * 60))) 28 | .set_parallelism(NonZero::new(5).unwrap()); 29 | 30 | let mut kademlia = kad::Behaviour::with_config(peer_id, store, config); 31 | kademlia.set_mode(Some(kad::Mode::Server)); 32 | kademlia 33 | } 34 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::net::AddrParseError; 2 | 3 | use eigensdk::{ 4 | services_blsaggregation::bls_aggregation_service_error::BlsAggregationServiceError, 5 | types::operator::OperatorTypesError, 6 | }; 7 | 8 | #[expect(clippy::large_enum_variant, reason = "SDK error is large currently")] 9 | #[derive(Debug, thiserror::Error)] 10 | pub enum TaskError { 11 | #[error("Blueprint SDK: {0}")] 12 | BlueprintSDK(#[from] blueprint_sdk::Error), 13 | #[error(transparent)] 14 | SolType(#[from] alloy_sol_types::Error), 15 | #[error(transparent)] 16 | BlsAggregationService(#[from] BlsAggregationServiceError), 17 | #[error("Aggregation: {0}")] 18 | Aggregation(String), 19 | #[error(transparent)] 20 | OperatorTypesError(#[from] OperatorTypesError), 21 | #[error("Aggregated response receiver closed")] 22 | AggregatedResponseReceiverClosed, 23 | #[error("Context: {0}")] 24 | Context(String), 25 | #[error(transparent)] 26 | Parse(#[from] AddrParseError), 27 | #[error("Runtime: {0}")] 28 | Runtime(String), 29 | #[error("Chain: {0}")] 30 | Chain(String), 31 | #[error("Task: {0}")] 32 | Task(String), 33 | } 34 | -------------------------------------------------------------------------------- /crates/pricing-engine/operator.toml: -------------------------------------------------------------------------------- 1 | # config/operator.toml 2 | 3 | # Path for the key-value store database 4 | database_path = "data/operator_db" # Relative to where binary is run 5 | 6 | # Path to the operator's signing keypair file 7 | keypair_path = "config/operator_keypair.bin" # Relative to where binary is run 8 | 9 | # How long generated quotes are valid (e.g., "5m", "300s") 10 | quote_validity_duration = "5m" 11 | 12 | # Address and port for the gRPC server to bind to 13 | rpc_bind_address = "0.0.0.0:50051" 14 | 15 | # --- Benchmarking Configuration --- 16 | # Command to execute for benchmarking (needs refinement based on blueprint) 17 | benchmark_command = "sleep" # Example: use a wrapper script later 18 | 19 | # Default arguments for the benchmark command 20 | benchmark_args = ["2"] # Example: sleep for 2 seconds 21 | 22 | # Maximum duration to let the benchmark process run 23 | benchmark_duration = "10s" 24 | 25 | # How often to sample metrics during benchmark 26 | benchmark_interval = "1s" 27 | 28 | # --- Pricing Configuration --- 29 | # Factor to convert benchmark results (e.g., avg CPU core) to price units (e.g., Wei per second) 30 | price_scaling_factor = 100.0 # Example: 100 Wei per avg CPU core per second 31 | -------------------------------------------------------------------------------- /crates/evm-extra/src/extract/tx.rs: -------------------------------------------------------------------------------- 1 | //! Extractor for EVM transactions. 2 | //! 3 | //! This module contains the extractor for EVM transactions. It is responsible for converting a transaction request into a job result that can be sent to the network. 4 | use alloy_consensus::Transaction; 5 | use alloy_rpc_types::TransactionRequest; 6 | use blueprint_core::{IntoJobResult, JobResult}; 7 | 8 | /// A Wrapper around a transaction request that will be signed and sent to the network. 9 | #[derive(Debug, Clone)] 10 | pub struct Tx(pub TransactionRequest); 11 | 12 | impl IntoJobResult for Tx { 13 | fn into_job_result(self) -> Option { 14 | let tx_bytes = match serde_json::to_vec(&self.0) { 15 | Ok(bytes) => bytes, 16 | Err(e) => { 17 | blueprint_core::error!("Failed to serialize transaction: {e}"); 18 | return Some(JobResult::Err(blueprint_core::Error::new(e))); 19 | } 20 | }; 21 | let job_result = JobResult::new(tx_bytes.into()); 22 | Some(job_result) 23 | } 24 | } 25 | 26 | impl From for Tx { 27 | fn from(tx: T) -> Self { 28 | Tx(TransactionRequest::from_transaction(tx)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /crates/macros/context-derive/src/tangle/client.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | use syn::DeriveInput; 3 | 4 | use crate::cfg::FieldInfo; 5 | 6 | /// Generate the `TangleClientContext` implementation for the given struct. 7 | pub fn generate_context_impl( 8 | DeriveInput { 9 | ident: name, 10 | generics, 11 | .. 12 | }: DeriveInput, 13 | config_field: FieldInfo, 14 | ) -> proc_macro2::TokenStream { 15 | let field_access_config = match config_field { 16 | FieldInfo::Named(ident) => quote! { self.#ident }, 17 | FieldInfo::Unnamed(index) => quote! { self.#index }, 18 | }; 19 | 20 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 21 | 22 | let config_ty = quote! { ::blueprint_sdk::contexts::tangle::TangleClient }; 23 | 24 | quote! { 25 | impl #impl_generics ::blueprint_sdk::contexts::tangle::TangleClientContext for #name #ty_generics #where_clause { 26 | async fn tangle_client(&self) -> std::result::Result<#config_ty, ::blueprint_sdk::clients::Error> { 27 | ::blueprint_sdk::contexts::tangle::TangleClientContext::tangle_client(&#field_access_config).await 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | evm_version = "shanghai" 3 | solc_version = "0.8.27" 4 | gas_limit = 5000000000 5 | deny_warnings = false 6 | via_ir = false 7 | optimizer = true 8 | optimizer_runs = 100 9 | 10 | 11 | src = "contracts/src" 12 | test = "contracts/test" 13 | out = "contracts/out" 14 | script = "contracts/script" 15 | cache_path = "contracts/cache" 16 | broadcast = "contracts/broadcast" 17 | libs = ["dependencies"] 18 | remappings = [ 19 | "@eigenlayer/=dependencies/eigenlayer-middleware-1.3.1/lib/eigenlayer-contracts/src/", 20 | "@eigenlayer-middleware/=dependencies/eigenlayer-middleware-1.3.1/", 21 | "eigenlayer-contracts/=dependencies/eigenlayer-middleware-1.3.1/lib/eigenlayer-contracts/", 22 | "forge-std-1.9.6/=dependencies/forge-std-1.9.6/", 23 | "incredible-squaring/=contracts/src/", 24 | ] 25 | 26 | [soldeer] 27 | recursive_deps = true 28 | remappings_location = "txt" 29 | remappings_version = false 30 | 31 | [dependencies] 32 | eigenlayer-middleware = { version = "1.3.1", git = "https://github.com/Layr-Labs/eigenlayer-middleware", rev = "fd26169c7f988a53ad9ca1e745f40754afed4ed4" } 33 | forge-std = "1.9.6" 34 | "@openzeppelin-contracts" = "4.7.0" 35 | -------------------------------------------------------------------------------- /crates/testing-utils/eigenlayer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-eigenlayer-testing-utils" 3 | version = "0.1.0-alpha.21" 4 | description = "EigenLayer-specific testing utilities for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-runner = { workspace = true, features = ["eigenlayer"] } 17 | blueprint-evm-extra.workspace = true 18 | blueprint-core = { workspace = true } 19 | blueprint-auth = { workspace = true } 20 | blueprint-manager-bridge = { workspace = true, features = ["server"] } 21 | blueprint-core-testing-utils = { workspace = true } 22 | blueprint-chain-setup = { workspace = true, features = ["std", "anvil"] } 23 | 24 | axum = { workspace = true } 25 | futures = { workspace = true } 26 | tempfile = { workspace = true } 27 | alloy-primitives = { workspace = true } 28 | alloy-provider = { workspace = true } 29 | eigensdk = { workspace = true } 30 | eigenlayer-contract-deployer = { workspace = true } 31 | tokio = { workspace = true, features = ["full"] } 32 | url = { workspace = true } 33 | -------------------------------------------------------------------------------- /crates/build-utils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-build-utils-v0.1.0-alpha.3...blueprint-build-utils-v0.1.0-alpha.4) - 2025-10-07 11 | 12 | ### Other 13 | 14 | - updated the following local packages: blueprint-std 15 | 16 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-build-utils-v0.1.0-alpha.2...blueprint-build-utils-v0.1.0-alpha.3) - 2025-05-09 17 | 18 | ### Other 19 | 20 | - updated the following local packages: blueprint-std 21 | 22 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-build-utils-v0.1.0-alpha.1...blueprint-build-utils-v0.1.0-alpha.2) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - remove unused dependencies (#915) 27 | 28 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-build-utils-v0.1.0-alpha.1) - 2025-04-08 29 | 30 | ### Other 31 | 32 | - Initial release 33 | -------------------------------------------------------------------------------- /crates/testing-utils/anvil/src/anvil.rs: -------------------------------------------------------------------------------- 1 | use blueprint_core::info; 2 | use blueprint_core_testing_utils::Error; 3 | use blueprint_std::sync::{Arc, Mutex}; 4 | use blueprint_std::time::Duration; 5 | 6 | /// Waits for the given `successful_responses` Mutex to be greater than or equal to `task_response_count`. 7 | /// 8 | /// # Errors 9 | /// - Returns `Error::WaitResponse` if the `successful_responses` Mutex lock fails. 10 | pub async fn wait_for_responses( 11 | successful_responses: Arc>, 12 | task_response_count: usize, 13 | timeout_duration: Duration, 14 | ) -> Result, tokio::time::error::Elapsed> { 15 | tokio::time::timeout(timeout_duration, async move { 16 | loop { 17 | let count = match successful_responses.lock() { 18 | Ok(guard) => *guard, 19 | Err(e) => { 20 | return Err(Error::WaitResponse(e.to_string())); 21 | } 22 | }; 23 | if count >= task_response_count { 24 | info!("Successfully received {} task responses", count); 25 | return Ok(()); 26 | } 27 | tokio::time::sleep(Duration::from_secs(1)).await; 28 | } 29 | }) 30 | .await 31 | } 32 | -------------------------------------------------------------------------------- /crates/evm-extra/src/filters/mod.rs: -------------------------------------------------------------------------------- 1 | //! Filter creation utilities for EVM events 2 | //! 3 | //! Provides utilities for creating RPC filters for EVM event subscriptions. 4 | //! These filters are used directly with the RPC provider to efficiently 5 | //! filter events at the node level. 6 | 7 | use alloy_primitives::Address; 8 | use alloy_rpc_types::Filter; 9 | use alloy_sol_types::SolEvent; 10 | 11 | /// Filter creation utilities for EVM contracts 12 | pub mod contract; 13 | /// Filter creation utilities for EVM events 14 | pub mod event; 15 | 16 | /// Creates a filter for a specific contract and event type 17 | #[must_use] 18 | pub fn create_event_filter(address: Address) -> Filter { 19 | Filter::new() 20 | .address(address) 21 | .event_signature(E::SIGNATURE_HASH) 22 | } 23 | 24 | /// Creates a filter for multiple event types from a single contract 25 | #[must_use] 26 | pub fn create_contract_filter(address: Address, event_signatures: &[&[u8; 32]]) -> Filter { 27 | Filter::new().address(address).events(event_signatures) 28 | } 29 | 30 | /// Creates a filter for a specific event type from any contract 31 | #[must_use] 32 | pub fn create_event_type_filter() -> Filter { 33 | Filter::new().event_signature(E::SIGNATURE_HASH) 34 | } 35 | -------------------------------------------------------------------------------- /crates/manager/bridge/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-manager-bridge" 3 | version = "0.1.0-alpha.9" 4 | description = "Bridge for Blueprint manager to service communication" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core.workspace = true 17 | blueprint-auth.workspace = true 18 | 19 | tokio = { workspace = true, features = ["net"] } 20 | tonic = { workspace = true, features = ["codegen", "transport", "prost"] } 21 | prost = { workspace = true, features = ["derive"] } 22 | thiserror.workspace = true 23 | tempfile.workspace = true 24 | zerocopy.workspace = true 25 | 26 | # Client 27 | hyper-util = { workspace = true, features = ["tokio"], optional = true } 28 | tokio-vsock = { workspace = true, optional = true } 29 | tower = { workspace = true, features = ["util"], optional = true } 30 | 31 | [build-dependencies] 32 | tonic-build = { workspace = true, features = ["prost"] } 33 | 34 | [features] 35 | default = ["tracing"] 36 | tracing = ["blueprint-core/tracing"] 37 | client = ["dep:hyper-util", "dep:tokio-vsock", "dep:tower"] 38 | server = ["tonic/router"] 39 | -------------------------------------------------------------------------------- /examples/incredible-squaring/incredible-squaring-lib/src/lib.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::runner::BackgroundService; 2 | use blueprint_sdk::runner::error::RunnerError; 3 | use blueprint_sdk::tangle::extract::{TangleArg, TangleResult}; 4 | use tokio::sync::oneshot; 5 | use tokio::sync::oneshot::Receiver; 6 | 7 | // The job ID (to be generated?) 8 | pub const XSQUARE_JOB_ID: u32 = 0; 9 | 10 | // The job function 11 | // 12 | // The arguments are made up of "extractors", which take a portion of the `JobCall` to convert into the 13 | // target type. 14 | // 15 | // The context is passed in as a parameter, and can be used to store any shared state between job calls. 16 | pub async fn square(TangleArg(x): TangleArg) -> TangleResult { 17 | let result = x * x; 18 | 19 | // The result is then converted into a `JobResult` to be sent back to the caller. 20 | TangleResult(result) 21 | } 22 | 23 | #[derive(Clone)] 24 | pub struct FooBackgroundService; 25 | 26 | impl BackgroundService for FooBackgroundService { 27 | async fn start(&self) -> Result>, RunnerError> { 28 | let (tx, rx) = oneshot::channel(); 29 | tokio::spawn(async move { 30 | let _ = tx.send(Ok(())); 31 | }); 32 | Ok(rx) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.config/hakari.toml: -------------------------------------------------------------------------------- 1 | # This file contains settings for `cargo hakari`. 2 | # See https://docs.rs/cargo-hakari/latest/cargo_hakari/config for a full list of options. 3 | 4 | hakari-package = "workspace-hack" 5 | 6 | # Format version for hakari's output. Version 4 requires cargo-hakari 0.9.22 or above. 7 | dep-format-version = "4" 8 | 9 | # Setting workspace.resolver = "2" or higher in the root Cargo.toml is HIGHLY recommended. 10 | # Hakari works much better with the v2 resolver. (The v2 and v3 resolvers are identical from 11 | # hakari's perspective, so you're welcome to set either.) 12 | # 13 | # For more about the new feature resolver, see: 14 | # https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver 15 | resolver = "3" 16 | 17 | # Add triples corresponding to platforms commonly used by developers here. 18 | # https://doc.rust-lang.org/rustc/platform-support.html 19 | platforms = [ 20 | "x86_64-unknown-linux-gnu", 21 | # "x86_64-apple-darwin", 22 | "aarch64-apple-darwin", 23 | # "x86_64-pc-windows-msvc", 24 | ] 25 | 26 | [final-excludes] 27 | third-party = [ 28 | { name = "subxt" }, 29 | { name = "tangle-subxt" }, 30 | ] 31 | 32 | # Write out exact versions rather than a semver range. (Defaults to false.) 33 | # exact-versions = true 34 | -------------------------------------------------------------------------------- /crates/contexts/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-contexts" 3 | version = "0.1.0-alpha.21" 4 | description = "Context providers for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-runner = { workspace = true } 17 | blueprint-std = { workspace = true } 18 | blueprint-clients = { workspace = true } 19 | blueprint-networking = { workspace = true, optional = true } 20 | blueprint-keystore = { workspace = true, optional = true } 21 | 22 | proc-macro2 = { workspace = true, optional = true } 23 | 24 | tangle-subxt = { workspace = true, optional = true } 25 | 26 | [features] 27 | default = ["std", "keystore"] 28 | std = ["blueprint-runner/std", "blueprint-std/std", "blueprint-clients/std", "blueprint-keystore?/std", "blueprint-networking?/std", "tangle-subxt?/std"] 29 | web = ["tangle-subxt?/web"] 30 | 31 | evm = ["blueprint-clients/evm"] 32 | eigenlayer = ["blueprint-clients/eigenlayer"] 33 | networking = ["dep:blueprint-networking", "dep:proc-macro2"] 34 | keystore = ["dep:blueprint-keystore"] 35 | tangle = ["dep:tangle-subxt", "blueprint-clients/tangle"] 36 | -------------------------------------------------------------------------------- /crates/crypto/bls/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-bls" 3 | version = "0.1.0-alpha.9" 4 | description = "tnt-bls crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-crypto-core = { workspace = true, features = ["bls"] } 14 | blueprint-std = { workspace = true } 15 | tnt-bls = { workspace = true } 16 | serde = { workspace = true } 17 | serde_bytes = { workspace = true, features = ["alloc"] } 18 | ark-serialize = { workspace = true } 19 | hex = { workspace = true, features = ["alloc"] } 20 | paste = { workspace = true } 21 | thiserror = { workspace = true } 22 | 23 | sha2 = { workspace = true, optional = true } 24 | 25 | [dev-dependencies] 26 | blueprint-crypto-hashing = { path = "../hashing", features = ["sha2"] } 27 | serde_json = { workspace = true, features = ["alloc"] } 28 | 29 | [features] 30 | default = ["std", "aggregation"] 31 | std = [ 32 | "ark-serialize/std", 33 | "blueprint-crypto-core/std", 34 | "blueprint-std/std", 35 | "serde/std", 36 | "serde_json/std", 37 | "serde_bytes/std", 38 | "tnt-bls/std", 39 | ] 40 | aggregation = ["sha2", "tnt-bls/std"] 41 | -------------------------------------------------------------------------------- /crates/crypto/tangle-pair-signer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-tangle-pair-signer" 3 | version = "0.1.0-alpha.14" 4 | description = "Pair signer for Tangle" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-std = { workspace = true } 14 | blueprint-crypto-core = { workspace = true, features = ["tangle"] } 15 | blueprint-crypto-sp-core = { workspace = true } 16 | 17 | k256 = { workspace = true, optional = true } 18 | serde = { workspace = true } 19 | tangle-subxt = { workspace = true } 20 | sp-core = { workspace = true } 21 | sp-runtime = { workspace = true } 22 | thiserror = { workspace = true } 23 | 24 | alloy-primitives = { workspace = true, optional = true } 25 | alloy-signer-local = { workspace = true, optional = true } 26 | 27 | [features] 28 | default = ["std", "evm"] 29 | std = [ 30 | "blueprint-crypto-core/std", 31 | "blueprint-crypto-sp-core/std", 32 | "blueprint-std/std", 33 | "serde/std", 34 | "tangle-subxt/std", 35 | "sp-runtime/std", 36 | "sp-core/std", 37 | ] 38 | web = [ 39 | "tangle-subxt/web", 40 | ] 41 | 42 | evm = [ 43 | "dep:alloy-primitives", 44 | "dep:alloy-signer-local", 45 | "dep:k256", 46 | ] 47 | -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/unnamed_fields.rs: -------------------------------------------------------------------------------- 1 | use blueprint_context_derive::{ 2 | EVMProviderContext, KeystoreContext, ServicesContext, TangleClientContext, 3 | }; 4 | use blueprint_sdk::contexts::instrumented_evm_client::EvmInstrumentedClientContext as _; 5 | use blueprint_sdk::contexts::keystore::KeystoreContext as _; 6 | use blueprint_sdk::contexts::services::ServicesContext as _; 7 | use blueprint_sdk::contexts::tangle::TangleClientContext as _; 8 | use blueprint_sdk::runner::config::BlueprintEnvironment; 9 | 10 | #[derive(KeystoreContext, EVMProviderContext, TangleClientContext, ServicesContext)] 11 | #[allow(dead_code)] 12 | struct MyContext( 13 | String, 14 | #[config] BlueprintEnvironment, 15 | #[call_id] Option, 16 | ); 17 | 18 | #[allow(dead_code)] 19 | fn main() { 20 | let body = async { 21 | let ctx = MyContext("bar".to_string(), BlueprintEnvironment::default(), None); 22 | let _keystore = ctx.keystore(); 23 | let _evm_provider = ctx.evm_client(); 24 | let tangle_client = ctx.tangle_client().await.unwrap(); 25 | let _services_client = ctx.services_client().await; 26 | let _services = tangle_client 27 | .services_client() 28 | .current_service_operators([0; 32], 0) 29 | .await; 30 | }; 31 | drop(body); 32 | } 33 | -------------------------------------------------------------------------------- /crates/clients/tangle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-client-tangle" 3 | version = "0.1.0-alpha.21" 4 | description = "Tangle client for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-runner = { workspace = true, features = ["tangle"] } 17 | blueprint-core = { workspace = true } 18 | blueprint-std = { workspace = true } 19 | blueprint-client-core = { workspace = true } 20 | blueprint-keystore = { workspace = true } 21 | blueprint-crypto-sp-core = { workspace = true } 22 | 23 | auto_impl = { workspace = true } 24 | serde = { workspace = true } 25 | serde_json = { workspace = true, features = ["alloc"] } 26 | sp-core = { workspace = true } 27 | tangle-subxt = { workspace = true } 28 | thiserror = { workspace = true } 29 | tokio = { workspace = true } 30 | 31 | [features] 32 | default = ["std", "tracing"] 33 | std = [ 34 | "blueprint-runner/std", 35 | "blueprint-client-core/std", 36 | "blueprint-keystore/std", 37 | "blueprint-std/std", 38 | "serde/std", 39 | "serde_json/std", 40 | "sp-core/std", 41 | "tangle-subxt/std", 42 | ] 43 | web = [ 44 | "tangle-subxt/web" 45 | ] 46 | 47 | tracing = ["blueprint-core/tracing"] 48 | -------------------------------------------------------------------------------- /examples/incredible-squaring/incredible-squaring-bin/build.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::build; 2 | use blueprint_sdk::tangle::blueprint; 3 | use incredible_squaring_blueprint_lib::square; 4 | use std::path::Path; 5 | use std::process; 6 | 7 | fn main() { 8 | let contract_dirs: Vec<&str> = vec!["./contracts"]; 9 | build::soldeer_install(); 10 | build::soldeer_update(); 11 | build::build_contracts(contract_dirs); 12 | 13 | println!("cargo::rerun-if-changed=../incredible-squaring-lib"); 14 | 15 | let blueprint = blueprint! { 16 | name: "experiment", 17 | master_manager_revision: "Latest", 18 | manager: { Evm = "ExperimentalBlueprint" }, 19 | jobs: [square] 20 | }; 21 | 22 | match blueprint { 23 | Ok(blueprint) => { 24 | // TODO: Should be a helper function probably 25 | let json = blueprint_sdk::tangle::metadata::macros::ext::serde_json::to_string_pretty( 26 | &blueprint, 27 | ) 28 | .unwrap(); 29 | std::fs::write( 30 | Path::new(env!("CARGO_WORKSPACE_DIR")).join("blueprint.json"), 31 | json.as_bytes(), 32 | ) 33 | .unwrap(); 34 | } 35 | Err(e) => { 36 | println!("cargo::error={e:?}"); 37 | process::exit(1); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-macros" 3 | version = "0.1.0-alpha.7" 4 | description = "Macros for the Tangle Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [lib] 16 | proc-macro = true 17 | 18 | [dependencies] 19 | proc-macro2.workspace = true 20 | quote.workspace = true 21 | syn = { workspace = true, features = [ 22 | "full", 23 | "parsing", 24 | # needed for `Hash` impls 25 | "extra-traits", 26 | "clone-impls", 27 | "printing", 28 | "proc-macro", 29 | ] } 30 | 31 | # EVM 32 | serde_json = { workspace = true, features = ["alloc"], optional = true } 33 | 34 | [dev-dependencies] 35 | blueprint-sdk = { path = "../sdk", features = ["macros", "std"] } 36 | serde = { workspace = true, features = ["derive"] } 37 | serde_json = { workspace = true, features = ["alloc"] } 38 | tokio = { workspace = true, features = ["full"] } 39 | trybuild.workspace = true 40 | rustversion.workspace = true 41 | 42 | # TODO(serial): Document features 43 | [features] 44 | default = [] 45 | evm = ["dep:serde_json"] 46 | __private = ["syn/visit-mut"] 47 | 48 | [package.metadata.cargo-public-api-crates] 49 | allowed = [] 50 | 51 | [package.metadata.docs.rs] 52 | all-features = true 53 | -------------------------------------------------------------------------------- /crates/manager/src/blueprint/native.rs: -------------------------------------------------------------------------------- 1 | use crate::sdk::utils::get_formatted_os_string; 2 | use blueprint_runner::config::Protocol; 3 | use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::sources::{BlueprintBinary, BlueprintSource}; 4 | 5 | pub struct FilteredBlueprint { 6 | pub blueprint_id: u64, 7 | pub services: Vec, 8 | pub sources: Vec, 9 | pub name: String, 10 | pub registration_mode: bool, 11 | pub protocol: Protocol, 12 | } 13 | 14 | #[must_use] 15 | pub fn get_blueprint_binary(blueprint_binaries: &[BlueprintBinary]) -> Option<&BlueprintBinary> { 16 | let os = get_formatted_os_string().to_lowercase(); 17 | let arch = std::env::consts::ARCH.to_lowercase(); 18 | for binary in blueprint_binaries { 19 | let binary_str = format!("{:?}", binary.os).to_lowercase(); 20 | if binary_str.contains(&os) || os.contains(&binary_str) || binary_str == os { 21 | let mut arch_str = format!("{:?}", binary.arch).to_lowercase(); 22 | 23 | if arch_str == "amd" { 24 | arch_str = "x86".to_string(); 25 | } else if arch_str == "amd64" { 26 | arch_str = "x86_64".to_string(); 27 | } 28 | 29 | if arch_str == arch { 30 | return Some(binary); 31 | } 32 | } 33 | } 34 | 35 | None 36 | } 37 | -------------------------------------------------------------------------------- /crates/qos/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.6](https://github.com/tangle-network/blueprint/compare/blueprint-qos-v0.1.0-alpha.5...blueprint-qos-v0.1.0-alpha.6) - 2025-10-02 11 | 12 | ### Other 13 | 14 | - update Cargo.toml dependencies 15 | 16 | ## [0.1.0-alpha.5](https://github.com/tangle-network/blueprint/compare/blueprint-qos-v0.1.0-alpha.4...blueprint-qos-v0.1.0-alpha.5) - 2025-08-11 17 | 18 | ### Fixed 19 | 20 | - *(ci)* fix Clippy & build issues (#1125) 21 | 22 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-qos-v0.1.0-alpha.3...blueprint-qos-v0.1.0-alpha.4) - 2025-08-06 23 | 24 | ### Other 25 | 26 | - update Cargo.toml dependencies 27 | 28 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-qos-v0.1.0-alpha.2...blueprint-qos-v0.1.0-alpha.3) - 2025-07-07 29 | 30 | ### Other 31 | 32 | - update Cargo.toml dependencies 33 | 34 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-qos-v0.1.0-alpha.1...blueprint-qos-v0.1.0-alpha.2) - 2025-07-03 35 | 36 | ### Other 37 | 38 | - update Cargo.toml dependencies 39 | -------------------------------------------------------------------------------- /crates/macros/context-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-context-derive" 3 | version = "0.1.0-alpha.13" 4 | description = "Procedural macros for deriving Context Extension traits from blueprint-sdk" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [lib] 16 | proc-macro = true 17 | 18 | [dependencies] 19 | syn = { workspace = true, default-features = true, features = ["full"] } 20 | quote = { workspace = true } 21 | proc-macro2 = { workspace = true } 22 | 23 | [dev-dependencies] 24 | blueprint-context-derive = { path = ".", features = ["std", "tangle", "evm", "networking"] } 25 | blueprint-sdk = { path = "../../sdk", features = [ 26 | "std", 27 | "macros", 28 | "evm", 29 | "tangle", 30 | "testing", 31 | "networking", 32 | "local-store", 33 | ] } 34 | 35 | trybuild = { workspace = true } 36 | 37 | # EVM Stuff 38 | alloy-network = { workspace = true } 39 | alloy-provider = { workspace = true } 40 | alloy-transport = { workspace = true } 41 | round-based = { workspace = true, features = ["derive"] } 42 | serde = { workspace = true } 43 | tangle-subxt = { workspace = true } 44 | 45 | [features] 46 | default = ["std"] 47 | networking = [] 48 | std = [] 49 | 50 | tangle = [] 51 | evm = [] 52 | -------------------------------------------------------------------------------- /cli/src/command/create/types.rs: -------------------------------------------------------------------------------- 1 | use clap::{Args, ValueEnum}; 2 | 3 | #[derive(Debug, Clone, Args)] 4 | pub struct CreateArgs { 5 | /// The name of the blueprint 6 | #[arg(short, long, value_name = "NAME", env = "NAME")] 7 | pub name: String, 8 | 9 | #[command(flatten)] 10 | pub blueprint_type: BlueprintType, 11 | } 12 | 13 | #[derive(Debug, Clone, Args, Default)] 14 | #[group(required = false, multiple = false)] 15 | pub struct BlueprintType { 16 | /// Create a Tangle blueprint 17 | #[arg(long, conflicts_with = "eigenlayer")] 18 | pub tangle: bool, 19 | 20 | /// Create an EigenLayer blueprint 21 | #[arg(long, value_name = "VARIANT", value_enum, num_args = 0..=1, default_missing_value = "bls")] 22 | pub eigenlayer: Option, 23 | } 24 | 25 | #[derive(Debug, Default, Clone, Copy, ValueEnum)] 26 | pub enum EigenlayerVariant { 27 | #[default] 28 | BLS, 29 | ECDSA, 30 | } 31 | 32 | impl BlueprintType { 33 | pub fn get_type(&self) -> Option { 34 | if self.eigenlayer.is_some() { 35 | self.eigenlayer.map(BlueprintVariant::Eigenlayer) 36 | } else if self.tangle { 37 | Some(BlueprintVariant::Tangle) 38 | } else { 39 | None 40 | } 41 | } 42 | } 43 | 44 | #[derive(Debug, Clone)] 45 | pub enum BlueprintVariant { 46 | Tangle, 47 | Eigenlayer(EigenlayerVariant), 48 | } 49 | -------------------------------------------------------------------------------- /crates/qos/src/error.rs: -------------------------------------------------------------------------------- 1 | use blueprint_core::error as core_error; 2 | use thiserror::Error; 3 | use tokio::sync::oneshot; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum Error { 7 | #[error("Heartbeat error: {0}")] 8 | Heartbeat(String), 9 | 10 | #[error("Metrics error: {0}")] 11 | Metrics(String), 12 | 13 | #[error("gRPC error: {0}")] 14 | Grpc(#[from] tonic::transport::Error), 15 | 16 | #[error("System metrics error: {0}")] 17 | SystemMetrics(String), 18 | 19 | #[error("Consumer error: {0}")] 20 | Consumer(String), 21 | 22 | #[error("{0}")] 23 | Other(String), 24 | 25 | #[error("JSON serialization/deserialization error: {0}")] 26 | Json(#[from] serde_json::Error), 27 | 28 | #[error("Grafana API error: {0}")] 29 | GrafanaApi(String), 30 | 31 | #[error("Docker connection error: {0}")] 32 | DockerConnection(String), 33 | 34 | #[error("Docker operation error: {0}")] 35 | DockerOperation(String), 36 | 37 | #[error("I/O error: {0}")] 38 | Io(#[from] std::io::Error), 39 | 40 | #[error("{0}")] 41 | Generic(String), 42 | 43 | #[error("Core error: {0}")] 44 | Core(#[from] core_error::Error), 45 | 46 | #[error("Oneshot receive error: {0}")] 47 | Recv(#[from] oneshot::error::RecvError), 48 | 49 | #[error("Assertion failed: {0}")] 50 | Assertion(String), 51 | } 52 | 53 | pub type Result = std::result::Result; 54 | -------------------------------------------------------------------------------- /crates/tangle-extra/src/filters.rs: -------------------------------------------------------------------------------- 1 | use blueprint_core::JobCall; 2 | use blueprint_core::error::BoxError; 3 | use tower::filter::Predicate; 4 | 5 | use super::extract::ServiceId; 6 | 7 | /// A [`Predicate`] that checks if the service ID matches the given in the job call. 8 | #[derive(Debug, Clone, Copy)] 9 | pub struct MatchesServiceId(pub u64); 10 | 11 | #[derive(Debug)] 12 | pub struct MismatchedServiceId { 13 | pub expected: u64, 14 | pub actual: u64, 15 | } 16 | 17 | impl core::fmt::Display for MismatchedServiceId { 18 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 19 | write!( 20 | f, 21 | "Mismatched service ID: expected {}, actual {}", 22 | self.expected, self.actual 23 | ) 24 | } 25 | } 26 | 27 | impl core::error::Error for MismatchedServiceId {} 28 | 29 | impl Predicate for MatchesServiceId { 30 | type Request = JobCall; 31 | fn check(&mut self, call: Self::Request) -> Result { 32 | let (mut parts, body) = JobCall::into_parts(call); 33 | let service_id = ServiceId::try_from(&mut parts)?; 34 | if service_id.0 == self.0 { 35 | Ok(JobCall::from_parts(parts, body)) 36 | } else { 37 | Err(Box::new(MismatchedServiceId { 38 | expected: self.0, 39 | actual: service_id.0, 40 | })) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/testing-utils/core/src/lib.rs: -------------------------------------------------------------------------------- 1 | use cargo_toml::Manifest; 2 | pub use error::TestRunnerError; 3 | pub use runner::TestRunner; 4 | use std::path::Path; 5 | 6 | mod error; 7 | pub use error::TestRunnerError as Error; 8 | 9 | pub mod runner; 10 | 11 | /// Reads the manifest at `path` 12 | /// 13 | /// # Errors 14 | /// 15 | /// * The manifest is invalid 16 | /// * The manifest does not have a `package` section 17 | pub fn read_cargo_toml_file>(path: P) -> std::io::Result { 18 | let manifest = cargo_toml::Manifest::from_path(path) 19 | .map_err(|err| std::io::Error::other(format!("Failed to read Cargo.toml: {err}")))?; 20 | if manifest.package.is_none() { 21 | return Err(std::io::Error::other( 22 | "No package section found in Cargo.toml", 23 | )); 24 | } 25 | 26 | Ok(manifest) 27 | } 28 | 29 | pub fn setup_log() { 30 | use tracing_subscriber::filter::LevelFilter; 31 | use tracing_subscriber::util::SubscriberInitExt; 32 | 33 | let _ = tracing_subscriber::fmt::SubscriberBuilder::default() 34 | .without_time() 35 | .with_span_events(tracing_subscriber::fmt::format::FmtSpan::NONE) 36 | .with_env_filter( 37 | tracing_subscriber::EnvFilter::builder() 38 | .with_default_directive(LevelFilter::INFO.into()) 39 | .from_env_lossy(), 40 | ) 41 | .finish() 42 | .try_init(); 43 | } 44 | -------------------------------------------------------------------------------- /crates/testing-utils/tangle/src/keys.rs: -------------------------------------------------------------------------------- 1 | use blueprint_keystore::backends::bn254::Bn254Backend; 2 | use blueprint_keystore::backends::tangle::TangleBackend; 3 | use blueprint_keystore::backends::tangle::bls::TangleBlsBackend; 4 | use blueprint_keystore::{Keystore, KeystoreConfig}; 5 | use std::path::Path; 6 | 7 | /// Injects the pre-made Tangle keys of the given name 8 | /// 9 | /// # Keys Generated 10 | /// - `SR25519`: Tangle Dev Key 11 | /// - `ED25519`: Tangle Dev Key 12 | /// - `ECDSA`: Tangle Dev Key 13 | /// - `BLS381`: Tangle Dev Key 14 | /// - `BLS377`: Tangle Dev Key 15 | /// - `BLS BN254`: Random 16 | /// 17 | /// # Names 18 | /// - "alice" 19 | /// - "bob" 20 | /// - "charlie" 21 | /// - "dave" 22 | /// - "eve" 23 | /// 24 | /// # Errors 25 | /// - May fail if the keystore path cannot be created or accessed 26 | /// - May fail if the key generation fails 27 | pub fn inject_tangle_key>( 28 | keystore_path: P, 29 | name: &str, 30 | ) -> Result<(), blueprint_keystore::Error> { 31 | let config = KeystoreConfig::new().fs_root(keystore_path); 32 | let keystore = Keystore::new(config)?; 33 | 34 | keystore.sr25519_generate_from_string(name)?; 35 | keystore.ed25519_generate_from_string(name)?; 36 | keystore.ecdsa_generate_from_string(name)?; 37 | keystore.bls381_generate_from_string(name)?; 38 | keystore.bls377_generate_from_string(name)?; 39 | keystore.bls_bn254_generate_new(None)?; 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /examples/incredible-squaring/incredible-squaring-lib/tests/e2e.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::Job; 2 | use blueprint_sdk::tangle::layers::TangleLayer; 3 | use blueprint_sdk::testing::tempfile; 4 | use blueprint_sdk::testing::utils::setup_log; 5 | use blueprint_sdk::testing::utils::tangle::{InputValue, OutputValue, TangleTestHarness}; 6 | use color_eyre::Result; 7 | use incredible_squaring_blueprint_lib::square; 8 | 9 | #[tokio::test] 10 | async fn test_incredible_squaring() -> Result<()> { 11 | color_eyre::install()?; 12 | setup_log(); 13 | 14 | // Initialize test harness (node, keys, deployment) 15 | let temp_dir = tempfile::TempDir::new()?; 16 | let harness = TangleTestHarness::setup(temp_dir).await?; 17 | 18 | // Setup service 19 | let (mut test_env, service_id, _blueprint_id) = harness.setup_services::<1>(false).await?; 20 | test_env.initialize().await?; 21 | 22 | // Add the job to the node, and start it 23 | test_env.add_job(square.layer(TangleLayer)).await; 24 | test_env.start(()).await?; 25 | 26 | // Submit job and wait for execution 27 | let job = harness 28 | .submit_job(service_id, 0, vec![InputValue::Uint64(5)]) 29 | .await?; 30 | let results = harness.wait_for_job_execution(service_id, job).await?; 31 | 32 | // Verify results match expected output 33 | harness.verify_job(&results, vec![OutputValue::Uint64(25)]); 34 | 35 | assert_eq!(results.service_id, service_id); 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /crates/router/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-router" 3 | version = "0.1.0-alpha.6" 4 | description = "Job routing utilities for the Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core.workspace = true 17 | bytes.workspace = true 18 | document-features = { workspace = true, features = ["default"] } 19 | pin-project-lite.workspace = true 20 | tower.workspace = true 21 | hashbrown = { workspace = true, default-features = false, features = ["default-hasher", "inline-more"] } 22 | futures = { workspace = true, features = ["alloc"] } 23 | 24 | [dev-dependencies] 25 | blueprint-sdk = { path = "../sdk", features = ["macros"]} 26 | tracing-subscriber = { version = "0.3", features = ["json", "env-filter"] } 27 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 28 | tower = { workspace = true, features = ["util", "timeout", "limit", "load-shed", "steer", "filter"] } 29 | 30 | [features] 31 | default = ["tracing"] 32 | 33 | #! `blueprint-router` is fully `no_std` compatible 34 | 35 | #! ### Core 36 | 37 | ## Enable [tracing] support 38 | ## 39 | ## [tracing]: https://crates.io/crates/tracing 40 | tracing = ["blueprint-core/tracing"] 41 | 42 | [package.metadata.docs.rs] 43 | all-features = true 44 | rustdoc-args = ["--cfg", "docsrs"] 45 | -------------------------------------------------------------------------------- /crates/benchmarking/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.5](https://github.com/tangle-network/blueprint/compare/blueprint-benchmarking-v0.1.0-alpha.4...blueprint-benchmarking-v0.1.0-alpha.5) - 2025-10-07 11 | 12 | ### Other 13 | 14 | - updated the following local packages: blueprint-std 15 | 16 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-benchmarking-v0.1.0-alpha.3...blueprint-benchmarking-v0.1.0-alpha.4) - 2025-05-09 17 | 18 | ### Other 19 | 20 | - updated the following local packages: blueprint-std 21 | 22 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-benchmarking-v0.1.0-alpha.2...blueprint-benchmarking-v0.1.0-alpha.3) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - remove unused dependencies (#915) 27 | 28 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-benchmarking-v0.1.0-alpha.1...blueprint-benchmarking-v0.1.0-alpha.2) - 2025-04-14 29 | 30 | ### Other 31 | 32 | - update Cargo.toml dependencies 33 | 34 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-benchmarking-v0.1.0-alpha.1) - 2025-04-08 35 | 36 | ### Other 37 | 38 | - Initial release 39 | -------------------------------------------------------------------------------- /crates/producers-extra/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-producers-extra" 3 | version = "0.1.0-alpha.6" 4 | description = "Additional job call producers for the Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [lints] 13 | workspace = true 14 | 15 | [dependencies] 16 | blueprint-core = { workspace = true } 17 | document-features = { workspace = true, features = ["default"] } 18 | futures = { workspace = true } 19 | 20 | # Cron 21 | chrono = { workspace = true, optional = true } 22 | tokio-cron-scheduler = { workspace = true, optional = true } 23 | tokio = { workspace = true, optional = true } 24 | 25 | [dev-dependencies] 26 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } 27 | 28 | [features] 29 | default = ["std"] 30 | 31 | #! By default, no producers will be available. You can enable them with their respective feature flags. 32 | 33 | #! ### Core 34 | 35 | ## Enable standard library support. Currently unused 36 | std = [] 37 | 38 | ## Enable [tracing] support 39 | ## 40 | ## [tracing]: https://crates.io/crates/tracing 41 | tracing = ["blueprint-core/tracing"] 42 | 43 | #! ### Extra producers 44 | 45 | ## A cron job producer 46 | cron = ["dep:tokio-cron-scheduler", "dep:chrono", "dep:tokio", "std"] 47 | 48 | [package.metadata.docs.rs] 49 | all-features = true 50 | rustdoc-args = ["--cfg", "docsrs"] 51 | -------------------------------------------------------------------------------- /crates/core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.5](https://github.com/tangle-network/blueprint/compare/blueprint-core-v0.1.0-alpha.4...blueprint-core-v0.1.0-alpha.5) - 2025-08-11 11 | 12 | ### Fixed 13 | 14 | - *(ci)* fix Clippy & build issues (#1125) 15 | 16 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-core-v0.1.0-alpha.3...blueprint-core-v0.1.0-alpha.4) - 2025-06-16 17 | 18 | ### Other 19 | 20 | - update Cargo.toml dependencies 21 | 22 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-core-v0.1.0-alpha.2...blueprint-core-v0.1.0-alpha.3) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - *(core)* improve documentation (#917) 27 | - remove unused dependencies (#915) 28 | 29 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-core-v0.1.0-alpha.1...blueprint-core-v0.1.0-alpha.2) - 2025-04-21 30 | 31 | ### Other 32 | 33 | - *(core)* [**breaking**] flatten job modules (#906) 34 | - *(core)* [**breaking**] remove `IntoJobId` trait (#905) 35 | 36 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-core-v0.1.0-alpha.1) - 2025-04-08 37 | 38 | ### Other 39 | 40 | - Initial release 41 | -------------------------------------------------------------------------------- /crates/crypto/hashing/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0-alpha.5](https://github.com/tangle-network/blueprint/compare/blueprint-crypto-hashing-v0.1.0-alpha.4...blueprint-crypto-hashing-v0.1.0-alpha.5) - 2025-10-07 11 | 12 | ### Other 13 | 14 | - updated the following local packages: blueprint-std 15 | 16 | ## [0.1.0-alpha.4](https://github.com/tangle-network/blueprint/compare/blueprint-crypto-hashing-v0.1.0-alpha.3...blueprint-crypto-hashing-v0.1.0-alpha.4) - 2025-05-09 17 | 18 | ### Other 19 | 20 | - updated the following local packages: blueprint-std 21 | 22 | ## [0.1.0-alpha.3](https://github.com/tangle-network/blueprint/compare/blueprint-crypto-hashing-v0.1.0-alpha.2...blueprint-crypto-hashing-v0.1.0-alpha.3) - 2025-05-01 23 | 24 | ### Other 25 | 26 | - remove unused dependencies (#915) 27 | 28 | ## [0.1.0-alpha.2](https://github.com/tangle-network/blueprint/compare/blueprint-crypto-hashing-v0.1.0-alpha.1...blueprint-crypto-hashing-v0.1.0-alpha.2) - 2025-04-21 29 | 30 | ### Other 31 | 32 | - update Cargo.toml dependencies 33 | 34 | ## [0.1.0-alpha.1](https://github.com/tangle-network/blueprint/releases/tag/blueprint-crypto-hashing-v0.1.0-alpha.1) - 2025-04-08 35 | 36 | ### Other 37 | 38 | - Initial release 39 | -------------------------------------------------------------------------------- /crates/chain-setup/common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-chain-setup-common" 3 | version = "0.1.0-alpha.21" 4 | description = "Common chain setup utilities for use with the Blueprint SDK" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-std = { workspace = true } 14 | color-eyre = { workspace = true } 15 | 16 | blueprint-tangle-extra = { workspace = true } 17 | blueprint-networking = { workspace = true } 18 | blueprint-contexts = { workspace = true, features = ["tangle"] } 19 | blueprint-crypto-tangle-pair-signer = { workspace = true, features = ["evm"] } 20 | blueprint-clients = { workspace = true, features = ["tangle"] } 21 | blueprint-keystore = { workspace = true, features = ["bn254", "bls", "sp-core"] } 22 | blueprint-crypto = { workspace = true, features = ["tangle-pair-signer"] } 23 | alloy-signer-local = { workspace = true } 24 | sp-core = { workspace = true } 25 | tangle-subxt = { workspace = true } 26 | thiserror = { workspace = true } 27 | 28 | [features] 29 | default = ["std"] 30 | std = [ 31 | "sp-core/std", 32 | "tangle-subxt/std", 33 | "blueprint-std/std", 34 | "blueprint-networking/std", 35 | "blueprint-contexts/std", 36 | "blueprint-crypto-tangle-pair-signer/std", 37 | "blueprint-crypto/std", 38 | "blueprint-clients/std", 39 | "blueprint-keystore/std", 40 | "thiserror/std", 41 | ] 42 | -------------------------------------------------------------------------------- /crates/macros/context-derive/src/tangle/services.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | use syn::DeriveInput; 3 | 4 | use crate::cfg::FieldInfo; 5 | 6 | /// Generate the `ServicesContext` implementation for the given struct. 7 | pub fn generate_context_impl( 8 | DeriveInput { 9 | ident: name, 10 | generics, 11 | .. 12 | }: DeriveInput, 13 | config_field: FieldInfo, 14 | ) -> proc_macro2::TokenStream { 15 | let field_access_config = match config_field { 16 | FieldInfo::Named(ident) => quote! { self.#ident }, 17 | FieldInfo::Unnamed(index) => quote! { self.#index }, 18 | }; 19 | 20 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 21 | 22 | let config_ty = quote! { 23 | ::blueprint_sdk::contexts::services::TangleServicesClient<::blueprint_sdk::tangle_subxt::subxt::PolkadotConfig> 24 | }; 25 | 26 | quote! { 27 | impl #impl_generics ::blueprint_sdk::contexts::services::ServicesContext for #name #ty_generics #where_clause { 28 | async fn services_client(&self) -> #config_ty { 29 | let rpc_client = ::blueprint_sdk::tangle_subxt::subxt::OnlineClient::from_insecure_url( 30 | &#field_access_config.http_rpc_endpoint 31 | ) 32 | .await 33 | .expect("Failed to create RPC client"); 34 | 35 | ::blueprint_sdk::contexts::services::TangleServicesClient::new(rpc_client) 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/crypto/bn254/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blueprint-crypto-bn254" 3 | version = "0.1.0-alpha.9" 4 | description = "Ark BN254 crypto primitives for Tangle Blueprints" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | homepage.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [dependencies] 13 | blueprint-crypto-core = { workspace = true, features = ["bn254"] } 14 | blueprint-std = { workspace = true } 15 | ark-bn254 = { workspace = true, features = ["scalar_field", "curve"] } 16 | ark-ec = { workspace = true } 17 | ark-ff = { workspace = true } 18 | ark-serialize = { workspace = true } 19 | serde = { workspace = true } 20 | serde_bytes = { workspace = true, features = ["alloc"] } 21 | thiserror = { workspace = true } 22 | num-bigint = { workspace = true, features = ["serde"] } 23 | num-traits = { workspace = true } 24 | sha2 = { workspace = true } 25 | hex = { workspace = true, features = ["alloc"] } 26 | 27 | [dev-dependencies] 28 | blueprint-crypto-hashing = { path = "../hashing", features = ["sha3"] } 29 | serde_json = { workspace = true, features = ["alloc"] } 30 | 31 | [features] 32 | default = ["std"] 33 | std = [ 34 | "blueprint-crypto-core/std", 35 | "blueprint-std/std", 36 | "serde/std", 37 | "serde_json/std", 38 | "serde_bytes/std", 39 | "ark-bn254/std", 40 | "ark-ec/std", 41 | "ark-ff/std", 42 | "ark-serialize/std", 43 | "num-bigint/std", 44 | "num-traits/std", 45 | "sha2/std", 46 | ] 47 | aggregation = [] 48 | -------------------------------------------------------------------------------- /crates/runner/src/eigenlayer/error.rs: -------------------------------------------------------------------------------- 1 | use eigensdk::{ 2 | client_avsregistry::error::AvsRegistryError, client_elcontracts::error::ElContractsError, 3 | }; 4 | use thiserror::Error; 5 | 6 | /// Errors that can occur within the Eigenlayer protocol runner 7 | #[derive(Debug, Error)] 8 | pub enum EigenlayerError { 9 | /// Errors from the Eigenlayer `AvsRegistry` 10 | #[error("AVS Registry error: {0}")] 11 | AvsRegistry(#[from] AvsRegistryError), 12 | 13 | /// Errors that occur when interacting with contracts 14 | #[error("Contract error: {0}")] 15 | Contract(#[from] alloy_contract::Error), 16 | 17 | /// Errors that occur when interacting with Eigenlayer contracts 18 | #[error("EL Contracts error: {0}")] 19 | ElContracts(#[from] ElContractsError), 20 | 21 | /// An error occured during operator registration 22 | #[error("Registration error: {0}")] 23 | Registration(String), 24 | 25 | /// Unable to open/interact with the provided [`Keystore`](blueprint_keystore::Keystore) 26 | #[error("Keystore error: {0}")] 27 | Keystore(#[from] blueprint_keystore::Error), 28 | 29 | /// Errors that occur when interacting with possibly malformed keys 30 | #[error("Crypto error: {0}")] 31 | Crypto(#[from] blueprint_crypto::CryptoCoreError), 32 | 33 | /// Unable to sign a message 34 | #[error("Signature error: {0}")] 35 | SignatureError(#[from] alloy_signer::Error), 36 | 37 | #[error("Other error: {0}")] 38 | Other(Box), 39 | } 40 | -------------------------------------------------------------------------------- /examples/incredible-squaring-eigenlayer/core_contracts.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxy_admin": "0x5fbdb2315678afecb367f032d93f642f64180aa3", 3 | "delegation_manager": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", 4 | "delegation_manager_impl": "0xc6e7df5e7b4f2a278906862b61205850344d4e7d", 5 | "avs_directory": "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9", 6 | "avs_directory_impl": "0x4ed7c70f96b99c776995fb64377f0d4ab3b0e1c1", 7 | "strategy_manager": "0x0165878a594ca255338adfa4d48449f69242eb8f", 8 | "strategy_manager_impl": "0x322813fd9a801c5507c9de605d63cea4f2ce6c44", 9 | "eigen_pod_manager": "0x959922be3caee4b8cd9a407cc3ac1c251c2007b1", 10 | "eigen_pod_manager_impl": "0x7a2088a1bfc9d81c55368ae168c2c02570cb814f", 11 | "allocation_manager": "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6", 12 | "allocation_manager_impl": "0x4a679253410272dd5232b3ff7cf5dbb88f295319", 13 | "rewards_coordinator": "0x610178da211fef7d417bc0e6fed39f05609ad788", 14 | "rewards_coordinator_impl": "0x09635f643e140090a9a8dcd712ed6285858cebef", 15 | "eigen_pod_beacon": "0xa51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0", 16 | "pauser_registry": "0x3aa5ebb10dc797cac828524e59a333d0a371443c", 17 | "strategy_factory": "0x9a676e781a523b5d0c0e43731313a708cb607508", 18 | "strategy_factory_impl": "0xa85233c63b9ee964add6f2cffe00fd84eb32338f", 19 | "strategy_beacon": "0xe6e340d132b5f46d1e472debcd681b2abc16e57e", 20 | "permission_controller": "0x68b1d87f95878fe05b998f19b66f4baba5de1aed", 21 | "permission_controller_impl": "0x59b670e9fa9d0a427751af201d676719a970857b" 22 | } -------------------------------------------------------------------------------- /crates/macros/context-derive/tests/ui/generic_struct.rs: -------------------------------------------------------------------------------- 1 | use blueprint_context_derive::{ 2 | EVMProviderContext, KeystoreContext, ServicesContext, TangleClientContext, 3 | }; 4 | use blueprint_sdk::contexts::instrumented_evm_client::EvmInstrumentedClientContext as _; 5 | use blueprint_sdk::contexts::keystore::KeystoreContext as _; 6 | use blueprint_sdk::contexts::services::ServicesContext as _; 7 | use blueprint_sdk::contexts::tangle::TangleClientContext as _; 8 | use blueprint_sdk::runner::config::BlueprintEnvironment; 9 | 10 | #[derive(KeystoreContext, EVMProviderContext, TangleClientContext, ServicesContext)] 11 | #[allow(dead_code)] 12 | struct MyContext { 13 | foo: T, 14 | bar: U, 15 | #[config] 16 | sdk_config: BlueprintEnvironment, 17 | #[call_id] 18 | call_id: Option, 19 | } 20 | 21 | #[allow(dead_code)] 22 | fn main() { 23 | let body = async { 24 | let ctx = MyContext { 25 | foo: "bar".to_string(), 26 | bar: 42, 27 | sdk_config: BlueprintEnvironment::default(), 28 | call_id: None, 29 | }; 30 | let _keystore = ctx.keystore(); 31 | let _evm_provider = ctx.evm_client(); 32 | let _tangle_client = ctx.tangle_client().await.unwrap(); 33 | let services_client = ctx.services_client().await; 34 | let _services = services_client 35 | .current_service_operators([0; 32], 0) 36 | .await 37 | .unwrap(); 38 | }; 39 | 40 | drop(body); 41 | } 42 | -------------------------------------------------------------------------------- /examples/oauth-blueprint/oauth-blueprint-bin/build.rs: -------------------------------------------------------------------------------- 1 | use blueprint_sdk::build; 2 | use blueprint_sdk::tangle::blueprint; 3 | use oauth_blueprint_lib::{write_doc, admin_purge}; 4 | 5 | fn main() { 6 | if std::env::var("BUILD_CONTRACTS").is_ok() { 7 | let contract_dirs: Vec<&str> = vec!["./contracts"]; 8 | build::soldeer_install(); 9 | build::soldeer_update(); 10 | build::build_contracts(contract_dirs); 11 | } 12 | 13 | println!("cargo::rerun-if-changed=../oauth-blueprint-lib"); 14 | 15 | // Re-run triggers 16 | println!("cargo:rerun-if-changed=contracts/src"); 17 | println!("cargo:rerun-if-changed=remappings.txt"); 18 | println!("cargo:rerun-if-changed=foundry.toml"); 19 | println!("cargo:rerun-if-changed=../oauth-blueprint-lib"); 20 | 21 | // Produce blueprint.json describing jobs in this blueprint 22 | let blueprint = blueprint! { 23 | name: "oauth-blueprint", 24 | master_manager_revision: "Latest", 25 | manager: { Evm = "ExperimentalBlueprint" }, 26 | jobs: [write_doc, admin_purge] 27 | }; 28 | 29 | if let Ok(blueprint) = blueprint { 30 | let json = 31 | blueprint_sdk::tangle::metadata::macros::ext::serde_json::to_string_pretty(&blueprint) 32 | .unwrap(); 33 | let root = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 34 | std::fs::write( 35 | std::path::Path::new(&root).join("blueprint.json"), 36 | json.as_bytes(), 37 | ) 38 | .unwrap(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/core/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc( 2 | html_logo_url = "https://cdn.prod.website-files.com/6494562b44a28080aafcbad4/65aaf8b0818b1d504cbdf81b_Tnt%20Logo.png" 3 | )] 4 | #![no_std] 5 | 6 | extern crate alloc; 7 | 8 | #[macro_use] 9 | pub(crate) mod macros; 10 | 11 | #[doc(hidden)] 12 | pub mod __private { 13 | pub use tracing; 14 | } 15 | 16 | pub mod error; 17 | pub mod ext_traits; 18 | pub mod extensions; 19 | pub mod extract; 20 | pub mod job; 21 | pub mod metadata; 22 | 23 | pub use bytes::Bytes; 24 | pub use error::Error; 25 | pub use ext_traits::job::{JobCallExt, JobCallPartsExt}; 26 | pub use extract::{FromJobCall, FromJobCallParts}; 27 | pub use job::call::JobCall; 28 | pub use job::result::{IntoJobResult, IntoJobResultParts, JobResult}; 29 | pub use job::{Job, JobId}; 30 | 31 | // Feature-gated tracing macros, used by the entire SDK 32 | macro_rules! tracing_macros { 33 | ($d:tt $($name:ident),*) => { 34 | $( 35 | #[doc(hidden)] 36 | #[cfg(feature = "tracing")] 37 | pub use tracing::$name; 38 | 39 | #[doc(hidden)] 40 | #[cfg(not(feature = "tracing"))] 41 | #[macro_export] 42 | macro_rules! $name { 43 | ($d($d tt:tt)*) => { 44 | if false { 45 | let _ = $crate::__private::tracing::$name!($d($d tt)*); 46 | } 47 | }; 48 | } 49 | )* 50 | } 51 | } 52 | 53 | tracing_macros!($ 54 | info, 55 | warn, 56 | error, 57 | debug, 58 | trace 59 | ); 60 | -------------------------------------------------------------------------------- /crates/core/src/job/future.rs: -------------------------------------------------------------------------------- 1 | //! Job future types. 2 | 3 | use crate::JobCall; 4 | use crate::JobResult; 5 | use crate::error::BoxError; 6 | use core::{future::Future, pin::Pin, task::Context}; 7 | use futures_util::future::Map; 8 | use pin_project_lite::pin_project; 9 | use tower::Service; 10 | use tower::util::Oneshot; 11 | 12 | type ServiceFutureInner = Map) -> Result, BoxError>>; 13 | 14 | opaque_future! { 15 | /// The response future for [`IntoService`](super::IntoService). 16 | pub type IntoServiceFuture = ServiceFutureInner; 17 | } 18 | 19 | type LayeredFutureInner = Map< 20 | Oneshot, 21 | fn( 22 | Result<>::Response, >::Error>, 23 | ) -> Option, 24 | >; 25 | 26 | pin_project! { 27 | /// The response future for [`Layered`](super::Layered). 28 | pub struct LayeredFuture 29 | where 30 | S: Service, 31 | { 32 | #[pin] 33 | inner: LayeredFutureInner, 34 | } 35 | } 36 | 37 | impl LayeredFuture 38 | where 39 | S: Service, 40 | { 41 | pub(super) fn new(inner: LayeredFutureInner) -> Self { 42 | Self { inner } 43 | } 44 | } 45 | 46 | impl Future for LayeredFuture 47 | where 48 | S: Service, 49 | { 50 | type Output = Option; 51 | 52 | #[inline] 53 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> core::task::Poll { 54 | self.project().inner.poll(cx) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/apikey-blueprint/apikey-blueprint-bin/build.rs: -------------------------------------------------------------------------------- 1 | use apikey_blueprint_lib::{purchase_api_key, write_resource}; 2 | use blueprint_sdk::build; 3 | use blueprint_sdk::tangle::blueprint; 4 | 5 | fn main() { 6 | if std::env::var("BUILD_CONTRACTS").is_ok() { 7 | let contract_dirs: Vec<&str> = vec!["./contracts"]; 8 | build::soldeer_install(); 9 | build::soldeer_update(); 10 | build::build_contracts(contract_dirs); 11 | } 12 | 13 | println!("cargo::rerun-if-changed=../apikey-blueprint-lib"); 14 | 15 | // Re-run triggers 16 | println!("cargo:rerun-if-changed=contracts/src"); 17 | println!("cargo:rerun-if-changed=remappings.txt"); 18 | println!("cargo:rerun-if-changed=foundry.toml"); 19 | println!("cargo:rerun-if-changed=../apikey-blueprint-lib"); 20 | 21 | // Produce blueprint.json describing jobs in this blueprint 22 | let blueprint = blueprint! { 23 | name: "apikey-blueprint", 24 | master_manager_revision: "Latest", 25 | manager: { Evm = "ExperimentalBlueprint" }, 26 | jobs: [write_resource, purchase_api_key] 27 | }; 28 | 29 | if let Ok(blueprint) = blueprint { 30 | let json = 31 | blueprint_sdk::tangle::metadata::macros::ext::serde_json::to_string_pretty(&blueprint) 32 | .unwrap(); 33 | let root = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 34 | std::fs::write( 35 | std::path::Path::new(&root).join("blueprint.json"), 36 | json.as_bytes(), 37 | ) 38 | .unwrap(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cli/src/foundry/mod.rs: -------------------------------------------------------------------------------- 1 | //! Foundry Utilities. 2 | use std::process::Command; 3 | 4 | mod forge; 5 | 6 | pub struct FoundryToolchain { 7 | pub forge: forge::Forge, 8 | } 9 | 10 | /// Trait for checking if a command is installed. 11 | trait CommandInstalled { 12 | /// Returns true if the command is installed. 13 | fn is_installed(&self) -> bool; 14 | } 15 | 16 | impl CommandInstalled for Command { 17 | fn is_installed(&self) -> bool { 18 | let cmd = self.get_program(); 19 | if cfg!(target_os = "windows") { 20 | Command::new("where") 21 | .arg(cmd) 22 | .output() 23 | .is_ok_and(|v| v.status.success()) 24 | } else { 25 | Command::new("which") 26 | .arg(cmd) 27 | .output() 28 | .is_ok_and(|v| v.status.success()) 29 | } 30 | } 31 | } 32 | 33 | impl Default for FoundryToolchain { 34 | fn default() -> Self { 35 | Self::new() 36 | } 37 | } 38 | 39 | impl FoundryToolchain { 40 | #[must_use] 41 | pub fn new() -> Self { 42 | Self { 43 | forge: forge::Forge::new(), 44 | } 45 | } 46 | pub fn check_installed_or_exit(&self) { 47 | fn foundry_installation_instructions() { 48 | eprintln!("Please install Foundry, follow https://getfoundry.sh/ for instructions."); 49 | } 50 | if !self.forge.is_installed() { 51 | eprintln!("Forge is not installed."); 52 | foundry_installation_instructions(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /crates/manager/src/sdk/entry.rs: -------------------------------------------------------------------------------- 1 | use futures::Future; 2 | use tracing_subscriber::EnvFilter; 3 | 4 | pub trait SendFuture<'a, T>: Send + Future + 'a {} 5 | impl<'a, F: Send + Future + 'a, T> SendFuture<'a, T> for F {} 6 | 7 | /// Sets up the logger for the blueprint manager, based on the verbosity level passed in. 8 | /// 9 | /// # Arguments 10 | /// 11 | /// * `verbose` - The verbosity level of the logger. 12 | /// * `pretty` - Whether to use pretty formatting for the logs. 13 | /// * `filter` - The filter to apply to the logs. 14 | /// 15 | /// # Errors 16 | /// 17 | /// * If the logger cannot be set up. 18 | /// 19 | /// # Returns 20 | /// 21 | /// * Empty result. 22 | pub fn setup_blueprint_manager_logger( 23 | verbose: u8, 24 | pretty: bool, 25 | filter: &str, 26 | ) -> color_eyre::Result<()> { 27 | use tracing::Level; 28 | let log_level = match verbose { 29 | 0 => Level::ERROR, 30 | 1 => Level::WARN, 31 | 2 => Level::INFO, 32 | 3 => Level::DEBUG, 33 | _ => Level::TRACE, 34 | }; 35 | let env_filter = 36 | EnvFilter::from_default_env().add_directive(format!("{filter}={log_level}").parse()?); 37 | let logger = tracing_subscriber::fmt() 38 | .with_target(false) 39 | .with_level(true) 40 | .with_line_number(false) 41 | .without_time() 42 | .with_max_level(log_level) 43 | .with_env_filter(env_filter); 44 | if pretty { 45 | let _ = logger.pretty().try_init(); 46 | } else { 47 | let _ = logger.compact().try_init(); 48 | } 49 | 50 | Ok(()) 51 | } 52 | -------------------------------------------------------------------------------- /crates/std/src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::boxed::Box; 2 | use crate::fmt::{self, Debug, Display}; 3 | use crate::string::String; 4 | 5 | pub trait Error: core::fmt::Debug + core::fmt::Display { 6 | fn source(&self) -> Option<&(dyn Error + 'static)> { 7 | None 8 | } 9 | } 10 | 11 | impl<'a, E: Error + 'a> From for Box { 12 | fn from(err: E) -> Self { 13 | Box::new(err) 14 | } 15 | } 16 | 17 | impl<'a, E: Error + Send + Sync + 'a> From for Box { 18 | fn from(err: E) -> Box { 19 | Box::new(err) 20 | } 21 | } 22 | 23 | impl Error for Box {} 24 | 25 | impl From for Box { 26 | #[inline] 27 | fn from(err: String) -> Box { 28 | struct StringError(String); 29 | 30 | impl Error for StringError {} 31 | 32 | impl Display for StringError { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | Display::fmt(&self.0, f) 35 | } 36 | } 37 | 38 | // Purposefully skip printing "StringError(..)" 39 | impl Debug for StringError { 40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 41 | Debug::fmt(&self.0, f) 42 | } 43 | } 44 | 45 | Box::new(StringError(err)) 46 | } 47 | } 48 | 49 | impl<'a> From<&'a str> for Box { 50 | #[inline] 51 | fn from(err: &'a str) -> Box { 52 | From::from(String::from(err)) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /crates/macros/tests/debug_job/fail/argument_not_extractor.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `bool: FromJobCall<(), blueprint_sdk::blueprint_core::extract::private::ViaParts>` is not satisfied 2 | --> tests/debug_job/fail/argument_not_extractor.rs:4:20 3 | | 4 | 4 | async fn job(_foo: bool) {} 5 | | ^^^^ the trait `FromJobCallParts<()>` is not implemented for `bool` 6 | | 7 | = note: Function argument is not a valid extractor. 8 | See `https://docs.rs/blueprint_sdk/latest/blueprint_sdk/extract/index.html` for details 9 | = help: the following other types implement trait `FromJobCallParts`: 10 | `()` implements `FromJobCallParts` 11 | `(T1, T2)` implements `FromJobCallParts` 12 | `(T1, T2, T3)` implements `FromJobCallParts` 13 | `(T1, T2, T3, T4)` implements `FromJobCallParts` 14 | `(T1, T2, T3, T4, T5)` implements `FromJobCallParts` 15 | `(T1, T2, T3, T4, T5, T6)` implements `FromJobCallParts` 16 | `(T1, T2, T3, T4, T5, T6, T7)` implements `FromJobCallParts` 17 | `(T1, T2, T3, T4, T5, T6, T7, T8)` implements `FromJobCallParts` 18 | and $N others 19 | = note: required for `bool` to implement `FromJobCall<(), blueprint_sdk::blueprint_core::extract::private::ViaParts>` 20 | note: required by a bound in `__blueprint_macros_check_job_0_from_job_check` 21 | --> tests/debug_job/fail/argument_not_extractor.rs:4:20 22 | | 23 | 4 | async fn job(_foo: bool) {} 24 | | ^^^^ required by this bound in `__blueprint_macros_check_job_0_from_job_check` 25 | -------------------------------------------------------------------------------- /crates/manager/src/rt/hypervisor/assets/user-data: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | disk_setup: 3 | /dev/vdc: 4 | # TODO: Change to gpt once https://github.com/canonical/cloud-init/issues/5797 is resolved 5 | table_type: mbr 6 | layout: true 7 | 8 | fs_setup: 9 | - device: /dev/vdc1 10 | filesystem: ext4 11 | overwrite: false 12 | label: DATADISK 13 | 14 | mounts: 15 | - [LABEL=SERVICEDISK, /srv, vfat, "ro,defaults,nofail", "0", "0"] 16 | - [LABEL=DATADISK, /mnt/data, "auto", "defaults,nofail,discard", "0", "2"] 17 | 18 | write_files: 19 | - path: /etc/systemd/system/launch.service 20 | content: | 21 | [Unit] 22 | Description=Service Launcher 23 | After=srv.mount mnt-data.mount docker.service 24 | 25 | [Service] 26 | Type=simple 27 | ExecStart=/srv/launch 28 | Restart=no 29 | KillSignal=SIGINT 30 | 31 | [Install] 32 | WantedBy=multi-user.target 33 | - path: /etc/docker/daemon.json 34 | owner: root:root 35 | permissions: '0644' 36 | content: | 37 | { "data-root": "/mnt/data/docker" } 38 | 39 | packages: 40 | - apt-transport-https 41 | - ca-certificates 42 | - curl 43 | - software-properties-common 44 | 45 | runcmd: 46 | # Enable virtiofs 47 | - sudo modprobe virtiofs 48 | 49 | # Install Docker using the official script 50 | - curl -fsSL https://get.docker.com -o get-docker.sh 51 | - sh get-docker.sh 52 | - usermod -aG docker ubuntu 53 | - systemctl enable --now docker 54 | 55 | # Enable and start the launch service after the disk is mounted 56 | - systemctl daemon-reload 57 | - systemctl enable --now launch.service 58 | -------------------------------------------------------------------------------- /crates/macros/src/evm/mod.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use quote::quote; 3 | use serde_json::Value; 4 | use std::path::PathBuf; 5 | use syn::parse::{Parse, ParseStream}; 6 | use syn::{Ident, LitStr, Token, parse_macro_input}; 7 | 8 | struct LoadAbiArgs { 9 | ident: Ident, 10 | _comma: Token![,], 11 | file_path: LitStr, 12 | } 13 | 14 | impl Parse for LoadAbiArgs { 15 | fn parse(input: ParseStream<'_>) -> syn::Result { 16 | Ok(LoadAbiArgs { 17 | ident: input.parse()?, 18 | _comma: input.parse()?, 19 | file_path: input.parse()?, 20 | }) 21 | } 22 | } 23 | 24 | pub fn load_abi(input: TokenStream) -> TokenStream { 25 | let LoadAbiArgs { 26 | ident, file_path, .. 27 | } = parse_macro_input!(input as LoadAbiArgs); 28 | let file_path = file_path.value(); 29 | 30 | let crate_root = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); 31 | let absolute_path = PathBuf::from(crate_root).join(file_path.clone()); 32 | 33 | if !absolute_path.exists() { 34 | return syn::Error::new_spanned( 35 | file_path, 36 | format!("ABI file not found at: {}", absolute_path.display()), 37 | ) 38 | .to_compile_error() 39 | .into(); 40 | } 41 | 42 | let file_content = std::fs::read_to_string(&absolute_path).expect("Failed to read ABI file"); 43 | 44 | let json: Value = serde_json::from_str(&file_content).expect("Failed to parse JSON"); 45 | 46 | let abi = json["abi"].to_string(); 47 | 48 | quote! { 49 | const #ident: &str = #abi; 50 | } 51 | .into() 52 | } 53 | -------------------------------------------------------------------------------- /cli/src/command/create/source.rs: -------------------------------------------------------------------------------- 1 | use clap::Args; 2 | use std::path::PathBuf; 3 | 4 | #[derive(Args, Debug, Clone, Default)] 5 | #[group(id = "source", required = false, multiple = false)] 6 | pub struct Source { 7 | #[command(flatten)] 8 | repo: Option, 9 | 10 | #[arg(short, long, group = "source")] 11 | path: Option, 12 | } 13 | 14 | #[derive(Args, Debug, Clone)] 15 | #[group(requires = "repo")] 16 | pub struct RepoArgs { 17 | #[arg(short, long, env, required = false, group = "source")] 18 | repo: String, 19 | #[arg(short, long, env)] 20 | branch: Option, 21 | #[arg(short, long, env, conflicts_with = "branch")] 22 | tag: Option, 23 | } 24 | 25 | impl From for Option { 26 | fn from(value: Source) -> Self { 27 | let mut template_path = cargo_generate::TemplatePath::default(); 28 | 29 | match value { 30 | Source { 31 | repo: Some(repo_args), 32 | .. 33 | } => { 34 | template_path.git = Some(repo_args.repo); 35 | template_path.branch = repo_args.branch; 36 | template_path.tag = repo_args.tag; 37 | Some(template_path) 38 | } 39 | Source { 40 | path: Some(path), .. 41 | } => { 42 | template_path.path = Some(path.to_string_lossy().into()); 43 | Some(template_path) 44 | } 45 | Source { 46 | repo: None, 47 | path: None, 48 | } => None, 49 | } 50 | } 51 | } 52 | --------------------------------------------------------------------------------