### Install Cargo-Tangle CLI (Source) Source: https://github.com/tangle-network/blueprint/blob/main/README.md Installs the latest git version of the `cargo-tangle` CLI directly from the GitHub repository. ```bash cargo install cargo-tangle --git https://github.com/tangle-network/blueprint --force ``` -------------------------------- ### Set Up Rust Environment (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Installs the Rust programming language, a specific nightly toolchain, and essential components like rustfmt and clippy. ```bash # Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install specific toolchain rustup install nightly-2024-10-13 rustup default nightly-2024-10-13 # Install required components rustup component add rustfmt clippy rust-src ``` -------------------------------- ### Install Dependencies (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Installs essential build tools and development libraries on Ubuntu/Debian and macOS systems. ```bash # Ubuntu/Debian apt install build-essential cmake libssl-dev pkg-config # macOS brew install openssl cmake ``` -------------------------------- ### Install Cargo-Tangle CLI (Script) Source: https://github.com/tangle-network/blueprint/blob/main/README.md Installs the latest stable version of the `cargo-tangle` CLI using a provided installation script. This is the recommended installation method. ```bash curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tangle-network/blueprint/releases/download/cargo-tangle/v0.1.1-beta.7/cargo-tangle-installer.sh | sh ``` -------------------------------- ### Install Dependencies and Compile Contracts (Bash/Yarn) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Installs Node.js dependencies for the blueprint and compiles the smart contracts using Forge. Assumes you are in the correct subdirectory. ```bash cd blueprints/incredible-squaring && yarn install ``` ```bash forge build --root ./contracts ``` -------------------------------- ### Rust Test Example for Tangle Blueprints Source: https://github.com/tangle-network/blueprint/blob/main/crates/testing-utils/tangle/README.md This Rust code snippet demonstrates how to use the Tangle Testing Framework to set up a test environment, initialize a blueprint context and event handler, deploy a service, and execute a job with verification. ```rust #[tokio::test] async fn test_my_blueprint() -> Result<()> { // Initialize test harness (node, keys, deployment) let harness = TangleTestHarness::setup().await?; // Create your blueprint context let blueprint_ctx = MyContext { env: harness.env.clone(), call_id: None, }; // Initialize your event handler let handler = MyEventHandler::new(&harness.env, blueprint_ctx).await?; // Setup service and run test let (_blueprint_id, service_id) = harness.setup_service(vec![handler]).await?; // Execute jobs and verify results let results = harness .execute_job( service_id, JOB_ID, inputs, expected_outputs, ) .await?; } ``` -------------------------------- ### Enable Full Blueprint Keystore Features (TOML) Source: https://github.com/tangle-network/blueprint/blob/main/crates/keystore/README.md This example demonstrates enabling a comprehensive set of features for the Blueprint Keystore in Cargo.toml, including full Tangle, EigenLayer, and all remote signing capabilities. ```toml blueprint-keystore = { version = "0.1", features = ["std", "tangle-full", "eigenlayer-full", "all-remote-signers"] } ``` -------------------------------- ### Deploy Tangle Blueprint to Local Node Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Deploys the blueprint to a local Tangle node. The `--devnet` flag automatically starts a local testnet, creates a keystore at `./deploy-keystore` (Bob's keys), and a test keystore at `./test-keystore` (Alice's keys). ```bash cargo tangle blueprint deploy tangle --devnet --package ``` ```bash cargo tangle blueprint deploy tangle --ws-rpc-url ws://localhost:9944 --keystore-path ./my-keystore --package my_blueprint ``` -------------------------------- ### Run Local Tangle Network (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Starts a standalone local Tangle Network. This is a prerequisite for running and deploying the blueprint locally. ```bash bash ./scripts/run-standalone-local.sh --clean ``` -------------------------------- ### Install OpenSSL Development Packages (Ubuntu/Debian) Source: https://github.com/tangle-network/blueprint/blob/main/README.md Installs necessary build tools and OpenSSL development packages required for building the Tangle CLI on Ubuntu or Debian-based systems. ```bash sudo apt update && sudo apt install build-essential cmake libssl-dev pkg-config ``` -------------------------------- ### Install OpenSSL and CMake (macOS) Source: https://github.com/tangle-network/blueprint/blob/main/README.md Installs OpenSSL and CMake using Homebrew, prerequisites for building the Tangle CLI on macOS. ```bash brew install openssl cmake ``` -------------------------------- ### Rust Async Test Examples (Rust) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Provides examples of writing asynchronous unit tests in Rust using the `tokio` runtime, including handling errors and concurrent operations. ```rust #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_async_feature() { // Async test implementation let result = some_async_function().await; assert!(result.is_ok()); } #[tokio::test] async fn test_error_handling() { // Async error handling test match failing_async_function().await { Err(e) => assert_matches!(e, Error::Expected), _ => panic!("Expected error"), } } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_concurrent_operations() { // Test concurrent operations let (result1, result2) = tokio::join!( async_operation1(), async_operation2() ); assert!(result1.is_ok() && result2.is_ok()); } } ``` -------------------------------- ### Deploy Blueprint Function Documentation (Rust) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Documents the `deploy_blueprint` function, a public API for deploying blueprints to the Tangle network. It includes arguments, return types, and usage examples. ```rust /// Deploys a blueprint to the network /// /// # Arguments /// /// * `name` - Name of the blueprint /// * `config` - Blueprint configuration /// /// # Returns /// /// * `Result` - Deployment identifier on success /// /// # Examples /// /// ``` /// let result = deploy_blueprint("my_blueprint", config)?; /// ``` pub fn deploy_blueprint(name: &str, config: Config) -> Result { // Implementation } ``` -------------------------------- ### Authenticated API Request Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Shows an example of an HTTP GET request to a protected API resource, requiring an Authorization header with a Bearer access token. ```http GET /api/v1/resource Authorization: Bearer v4.local.xxxxx ``` -------------------------------- ### Migrate from Legacy Tokens to API Keys Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Provides a TypeScript code example comparing the older method of authentication using legacy tokens with the newer method using API keys and access tokens with the AuthClient. The new method is more secure and organized. ```typescript // Before (Legacy) const token = `${tokenId}|${tokenSecret}`; fetch('/api/resource', { headers: { 'Authorization': `Bearer ${token}` } }); // After (API Keys + Access Tokens) const client = new AuthClient({ apiKey: 'ak_xxxxx.yyyyy', serviceUrl: 'https://api.example.com' }); const data = await client.request('/api/resource'); ``` -------------------------------- ### Create, Build, and Deploy Tangle Blueprint Source: https://github.com/tangle-network/blueprint/blob/main/README.md Demonstrates the basic workflow for creating a new blueprint, navigating into its directory, building it, and deploying it to the Tangle Network. ```bash # Create a new blueprint named "my_blueprint" cargo tangle blueprint create --name my_blueprint # Navigate into the blueprint directory and build cd my_blueprint cargo build # Deploy your blueprint to the Tangle Network cargo tangle blueprint deploy --rpc-url wss://rpc.tangle.tools --package my_blueprint ``` -------------------------------- ### Build and Run Operator Server (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/crates/pricing-engine/README.md Provides the command-line instructions to build the Rust project in release mode and then run the operator RFQ gRPC server. ```bash # Build the server cargo build --release # Run the gRPC server cargo run --bin operator_rfq ``` -------------------------------- ### Run Incredible Squaring Blueprint (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Runs the blueprint on a local Tangle Network. It configures logging, service discovery, and the base path for the keystore. ```bash RUST_LOG=blueprint_sdk=trace,error cargo run -p incredible-squaring-blueprint -- run --url=ws://localhost:9944 --base-path=./target/keystore --blueprint-id=0 --service-id=0 --target-addr=0.0.0.0 --target-port= ``` -------------------------------- ### Enable Blueprint Keystore Features (TOML) Source: https://github.com/tangle-network/blueprint/blob/main/crates/keystore/README.md This snippet shows how to configure the Blueprint Keystore dependency in a Cargo.toml file, specifying the required features for standard library support, ECDSA, remote signing, and AWS KMS integration. ```toml [dependencies] blueprint-keystore = { version = "0.1", features = ["std", "ecdsa", "remote", "aws-signer"] } ``` -------------------------------- ### Build Incredible Squaring Blueprint (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Builds the blueprint using Cargo. Ensure you are in the project root directory. ```bash cargo build -p incredible-squaring-blueprint ``` -------------------------------- ### Create New Tangle Blueprint Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Creates a new Tangle blueprint with a specified name. This command initializes the necessary files and structure for a new blueprint project. ```bash cargo tangle blueprint create --name ``` ```bash cargo tangle blueprint create --name my_blueprint ``` -------------------------------- ### Add Alice to Local Keystore (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Adds Alice's key to the local keystore, which is used by the blueprint for signing transactions. The provided key is a placeholder. ```bash echo -n "e5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a" > target/keystore/0000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d ``` -------------------------------- ### Set Environment Variables for Deployment Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Sets optional environment variables for signing during blueprint deployment. `SIGNER` is for the Substrate account, and `EVM_SIGNER` is for the EVM account. These are not prioritized over a provided keystore. ```bash export SIGNER="//Alice" # Substrate Signer account ``` ```bash export EVM_SIGNER="0xcb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854" # EVM signer account ``` -------------------------------- ### Format Code with Rustfmt (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Applies the standard Rust code formatting rules to the entire project using the `rustfmt` tool. ```bash cargo fmt ``` -------------------------------- ### Clone and Navigate Repository (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Clones the Tangle Network Blueprint repository from GitHub and changes the current directory into the project root. ```bash git clone https://github.com/tangle-network/blueprint.git cd blueprint ``` -------------------------------- ### Returning Routers with Contexts Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Illustrates the recommended way to return routers with contexts from functions. Avoid calling `Router::with_context` within the function; instead, apply it before running the server. This ensures compatibility with `BlueprintRunner::router`. ```rust use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; const MY_JOB_ID: u8 = 0; #[derive(Clone)] struct AppContext {} // Don't call `Router::with_context` here fn routes() -> Router { Router::new() .route(MY_JOB_ID, |_: Context| async {}) } // Instead, do it before you run the server let routes = routes().with_context(AppContext {}); # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(routes); let result = runner.run().await; # }; ``` -------------------------------- ### Run Unit Tests for Tangle Blueprint Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Executes all unit tests defined within the Tangle blueprint project. This ensures the components of the blueprint function correctly. ```bash cargo test ``` -------------------------------- ### Lint Code with Clippy (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Analyzes Rust code for common mistakes and style issues using the `clippy` linter, with warnings treated as errors. ```bash cargo clippy -- -D warnings ``` -------------------------------- ### Provide Router Context Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Demonstrates how to provide a context to a Blueprint router. The context is global and used for all requests the router receives. It requires the `blueprint_sdk` crate. ```rust use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; const MY_JOB_ID: u8 = 0; #[derive(Clone)] struct AppContext {} let routes = Router::new() .route(MY_JOB_ID, |Context(ctx): Context| async { // use context }) .with_context(AppContext {}); # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(routes); let result = runner.run().await; # }; ``` -------------------------------- ### Correct Context Handling in Blueprint Router Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Illustrates the correct method for defining routes by returning `Router<()>` after successfully providing all necessary context via `with_context`. This allows the router to be compatible with `BlueprintRunnerBuilder::router`. ```rust # use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; # const MY_JOB_ID: u8 = 0; # #[derive(Clone)] # struct AppContext {} # // We've provided all the context necessary so return `Router<()>` fn routes(context: AppContext) -> Router<()> { Router::new() .route(MY_JOB_ID, |_: Context| async {}) .with_context(context) } let app = routes(AppContext {}); // We can now call `BlueprintRunnerBuilder::router` # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(app); let result = runner.run().await; # }; ``` -------------------------------- ### Build Tangle Blueprint Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Builds the Tangle blueprint project using cargo. This command compiles the Rust code for the blueprint, similar to any standard Rust project. ```bash cargo build ``` -------------------------------- ### Deploy Blueprint to Tangle (Yarn) Source: https://github.com/tangle-network/blueprint/blob/main/examples/incredible-squaring/README.md Deploys the blueprint to the Tangle network using a TypeScript script. This also creates a service instance for interaction. ```bash yarn tsx deploy.ts ``` -------------------------------- ### Create Feature Branch (Bash) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Creates a new Git branch for developing a new feature, following a standard naming convention. ```bash git checkout -b feature/your-feature-name ``` -------------------------------- ### Returning Generic Router Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Shows how to return a generic `Router` when context needs to be provided externally. This `Router` does not have type parameters for context, allowing `with_context` to be called later. Requires `blueprint_sdk`. ```rust # use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; # const MY_JOB_ID: u8 = 0; # #[derive(Clone)] # struct AppContext {} # // Don't return `Router` fn routes(context: AppContext) -> Router { Router::new() .route(MY_JOB_ID, |_: Context| async {}) // Note: context not used in this example route .with_context(context) } let routes = routes(AppContext {}); # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(routes); let result = runner.run().await; # }; ``` -------------------------------- ### Generate Keys from Command Line Source: https://github.com/tangle-network/blueprint/blob/main/cli/README.md Generates a keypair for a specified key type at an optional path, using an optional SURI/seed. The `--show-secret` flag can be used to display the secret key. ```bash cargo tangle blueprint generate-keys -k -p -s --show-secret ``` -------------------------------- ### Conventional Commit Message Format (Text) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Illustrates the structure and types for writing conventional commit messages, aiding in automated changelog generation and semantic versioning. ```text (): [optional body] [optional footer] Types: - feat: New feature - fix: Bug fix - docs: Documentation changes - style: Code style changes (formatting, missing semi-colons, etc) - refactor: Code refactoring - test: Adding missing tests - chore: Maintenance tasks Example: feat(cli): add new blueprint deployment option Added --dry-run flag to deployment command for testing deployments without actually submitting transactions. Closes #123 ``` -------------------------------- ### Mock Authentication Client for Testing (TypeScript) Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md A mock implementation of the AuthClient for testing purposes. It provides stubbed methods for token exchange and API requests, returning predefined mock data. ```typescript // auth-client.test.ts export class MockAuthClient extends AuthClient { private mockToken = 'v4.local.mock_token_for_testing'; async exchangeToken(options?: TokenExchangeRequest): Promise { const now = Math.floor(Date.now() / 1000); return { access_token: this.mockToken, token_type: 'Bearer', expires_at: now + 900, // 15 minutes expires_in: 900, }; } async request(path: string, options: RequestInit = {}): Promise { // Mock successful response return { success: true, path } as T; } } ``` -------------------------------- ### Rust Quote Signature Format Source: https://github.com/tangle-network/blueprint/blob/main/crates/pricing-engine/README.md Defines the structure of a price quote payload for signing and verification, including the blueprint hash, price, and timestamp/block number. It outlines the hashing (SHA256) and signing (ed25519) process. ```rust struct QuotePayload { blueprint_hash: [u8; 32], price_wei: u128, timestamp_or_block: u64, } // Hash with `sha256`, sign with `ed25519`: let msg = sha256(encode(&QuotePayload)); let sig = keypair.sign(&msg); ``` -------------------------------- ### Rust Time-Dependent Test Mocking (Rust) Source: https://github.com/tangle-network/blueprint/blob/main/CONTRIBUTING.md Demonstrates how to mock time-dependent behavior in Rust tests using `tokio::time` for intervals and sleeps. ```rust use tokio::time::{self, Duration}; #[tokio::test] async fn test_with_time() { let mut interval = time::interval(Duration::from_secs(1)); // First tick completes immediately interval.tick().await; // Use time::sleep for testing timeouts tokio::time::sleep(Duration::from_secs(2)).await; // Test after delay assert!(some_condition); } ``` -------------------------------- ### Performance Optimization with `with_context(())` Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Shows how to optimize a Blueprint Router for performance when no application context is needed, by calling `with_context(())` explicitly. This can improve performance and reduce allocations by allowing internal router updates. ```rust use blueprint_sdk::Router; const MY_JOB_ID: u8 = 0; let app = Router::new() .route(MY_JOB_ID, || async { /* ... */ }) // even though we don't need any context, call `with_context(())` anyway .with_context(()); # let _: Router = app; ``` -------------------------------- ### Chaining Contexts with with_context Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Demonstrates how `Router::with_context` allows specifying the *next* missing context type. This enables chaining routes with different context requirements, ultimately leading to a `Router<()>` for execution. ```rust # use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; # const MY_JOB_ID: u8 = 0; # #[derive(Clone)] # struct AppContext {} # let router: Router = Router::new() .route(MY_JOB_ID, |_: Context| async {}); // When we call `with_context` we're able to pick what the next missing context type is. // Here we pick `String`. let string_router: Router = router.with_context(AppContext {}); // That allows us to add new routes that uses `String` as the context type const NEEDS_STRING_JOB_ID: u8 = 1; let string_router = string_router .route(NEEDS_STRING_JOB_ID, |_: Context| async {}); // Provide the `String` and choose `()` as the new missing context. let final_router: Router<()> = string_router.with_context("foo".to_owned()); // Since we have a `Router<()>` we can run it. # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(final_router); let result = runner.run().await; # }; ``` -------------------------------- ### Tangle Network Handshake Protocol Sequence Source: https://github.com/tangle-network/blueprint/blob/main/crates/networking/README.md Visualizes the step-by-step process of two nodes establishing a secure connection through identity verification and signature exchange before communication can begin. This ensures mutual trust and prevents unauthorized access. ```mermaid sequenceDiagram participant A as Node A participant B as Node B Note over A,B: Step 1: Initial Connection A->>B: Hi! Here's my ID and signature Note right of B: Step 2: B checks A's identity B->>A: Hi back! Here's my ID and signature Note left of A: Step 3: A checks B's identity Note over A,B: Step 4: Both nodes are now friends! ``` -------------------------------- ### Multi-Tenant Authentication Client (TypeScript) Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Extends the base AuthClient to support multi-tenancy by adding a tenant ID to outgoing requests. It clears cached tokens when the tenant context changes. ```typescript // multi-tenant-client.ts export class MultiTenantAuthClient extends AuthClient { private tenantId?: string; setTenant(tenantId: string) { this.tenantId = tenantId; // Clear cached token when tenant changes this.accessToken = undefined; } async exchangeToken(options?: TokenExchangeRequest): Promise { const headers: Record = {}; if (this.tenantId) { // Add tenant ID as a header that will be embedded in the access token headers['X-Tenant-ID'] = this.tenantId; } return super.exchangeToken({ ...options, additional_headers: { ...options?.additional_headers, ...headers, }, }); } } // Usage example const client = new MultiTenantAuthClient({ apiKey: 'ak_2n4f8dhqp3k5.w9x7y6z5a4b3c2d1e0f9g8h7', serviceUrl: 'https://api.tangle.network', }); // Set tenant context client.setTenant('tenant-123'); // Make tenant-scoped request const data = await client.request('/api/v1/resources'); ``` -------------------------------- ### TypeScript AuthClient for Token Exchange and Requests Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Implements an `AuthClient` class in TypeScript to manage the authentication workflow. It handles exchanging API keys for short-lived access tokens, automatically refreshing tokens before expiration, and making authenticated API requests. It requires `ServiceCredentials` and utilizes `AccessToken` types. ```typescript // auth-client.ts export class AuthClient { private apiKey: string; private baseUrl: string; private accessToken?: AccessToken; private tokenRefreshTimer?: NodeJS.Timeout; constructor(config: ServiceCredentials) { this.apiKey = config.apiKey; this.baseUrl = config.serviceUrl; } /** * Exchange API key for a short-lived access token */ async exchangeToken(options?: TokenExchangeRequest): Promise { const response = await fetch(`${this.baseUrl}/v1/auth/exchange`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify(options || {}), }); if (!response.ok) { throw new Error(`Token exchange failed: ${response.statusText}`); } const token: AccessToken = await response.json(); this.accessToken = token; // Setup automatic refresh before expiration this.scheduleTokenRefresh(token.expires_in); return token; } /** * Get current access token, refreshing if needed */ async getAccessToken(): Promise { if (!this.accessToken || this.isTokenExpired()) { await this.exchangeToken(); } return this.accessToken!.access_token; } private isTokenExpired(): boolean { if (!this.accessToken) return true; const now = Math.floor(Date.now() / 1000); // Refresh 30 seconds before expiration return now >= (this.accessToken.expires_at - 30); } private scheduleTokenRefresh(expiresIn: number) { if (this.tokenRefreshTimer) { clearTimeout(this.tokenRefreshTimer); } // Refresh 1 minute before expiration const refreshIn = (expiresIn - 60) * 1000; if (refreshIn > 0) { this.tokenRefreshTimer = setTimeout(() => { this.exchangeToken().catch(console.error); }, refreshIn); } } /** * Make an authenticated request */ async request( path: string, options: RequestInit = {} ): Promise { const token = await this.getAccessToken(); const response = await fetch(`${this.baseUrl}${path}`, { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${token}`, }, }); if (!response.ok) { throw new Error(`Request failed: ${response.statusText}`); } return response.json(); } /** * Cleanup timers */ dispose() { if (this.tokenRefreshTimer) { clearTimeout(this.tokenRefreshTimer); } } } ``` -------------------------------- ### Understanding Router Type Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Explains that `Router` signifies a router missing a context of type `Ctx`. After providing the context via `with_context`, the router type becomes `Router<()>` (missing no context). Only `Router<()>` can be used with `BlueprintRunner`. ```rust # use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; # const MY_JOB_ID: u8 = 0; # #[derive(Clone)] # struct AppContext {} # // A router that _needs_ an `AppContext` to handle requests let router: Router = Router::new() .route(MY_JOB_ID, |_: Context| async {}); // Once we call `Router::with_context` the router isn't missing // the context anymore, because we just provided it // // Therefore the router type becomes `Router<()>`, i.e a router // that is not missing any context let router: Router<()> = router.with_context(AppContext {}); // Only `Router<()>` can be used in a `BlueprintRunner`. // // You cannot call `BlueprintRunnerBuilder::router` with a `Router` // because it is still missing an `AppContext`. # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(router); let result = runner.run().await; # }; ``` -------------------------------- ### React Auth Hook (TypeScript) Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md A React hook to manage authentication state and provide API request functionality. It handles token exchange, loading, and errors, and includes a cleanup mechanism for the AuthClient. ```typescript // useAuth.tsx import { useEffect, useState, useCallback } from 'react'; import { AuthClient } from './auth-client'; interface UseAuthOptions { apiKey: string; serviceUrl: string; } export function useAuth({ apiKey, serviceUrl }: UseAuthOptions) { const [client] = useState(() => new AuthClient({ apiKey, serviceUrl })); const [isAuthenticated, setIsAuthenticated] = useState(false); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { // Initial token exchange client.exchangeToken() .then(() => { setIsAuthenticated(true); setError(null); }) .catch((err) => { setError(err); setIsAuthenticated(false); }) .finally(() => { setIsLoading(false); }); // Cleanup on unmount return () => { client.dispose(); }; }, [client]); const request = useCallback(async ( path: string, options?: RequestInit ): Promise => { try { return await client.request(path, options); } catch (err) { setError(err as Error); throw err; } }, [client]); return { isAuthenticated, isLoading, error, request, }; } // Usage in component function MyComponent() { const { isAuthenticated, isLoading, error, request } = useAuth({ apiKey: process.env.REACT_APP_API_KEY!, serviceUrl: process.env.REACT_APP_SERVICE_URL!, }); useEffect(() => { if (isAuthenticated) { request('/api/v1/data') .then(data => console.log(data)) .catch(console.error); } }, [isAuthenticated, request]); if (isLoading) return
Authenticating...
; if (error) return
Auth error: {error.message}
; return
Authenticated!
; } ``` -------------------------------- ### Token Exchange API Request Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Demonstrates the HTTP POST request to the /v1/auth/exchange endpoint for obtaining an access token. Requires an Authorization header with a Bearer token and a JSON body containing additional headers and TTL. ```http POST /v1/auth/exchange Authorization: Bearer ak_xxxxx.yyyyy Content-Type: application/json { "additional_headers": { "X-Tenant-ID": "tenant-123" }, "ttl_seconds": 600 } ``` -------------------------------- ### Tangle Network Direct P2P Message Sequence Source: https://github.com/tangle-network/blueprint/blob/main/crates/networking/README.md Illustrates the communication flow for a direct peer-to-peer message between two nodes after a successful handshake. It shows a message being sent and a confirmation response. ```mermaid sequenceDiagram participant A as Node A participant B as Node B A->>B: Direct message to B B->>A: Got it! Here's my response ``` -------------------------------- ### Resilient Authentication Client with Retry Logic (TypeScript) Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Extends the AuthClient to implement retry logic for API requests, particularly for authentication-related errors (401, 403). It uses exponential backoff for delays between retries. ```typescript // auth-with-retry.ts export class ResilientAuthClient extends AuthClient { private maxRetries = 3; private retryDelay = 1000; // Start with 1 second async request( path: string, options: RequestInit = {}, retryCount = 0 ): Promise { try { return await super.request(path, options); } catch (error: any) { // Check if error is auth-related if (error.message?.includes('401') || error.message?.includes('403')) { if (retryCount < this.maxRetries) { // Clear cached token and retry this.accessToken = undefined; // Exponential backoff const delay = this.retryDelay * Math.pow(2, retryCount); await new Promise(resolve => setTimeout(resolve, delay)); return this.request(path, options, retryCount + 1); } } throw error; } } } ``` -------------------------------- ### TypeScript Types for Authentication Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Defines the data structures for API keys, access tokens, token exchange requests, and service credentials used within the Tangle Blueprint SDK authentication system. These types ensure type safety and clarity for authentication-related operations. ```typescript // types.ts export interface ApiKey { key: string; // Format: "ak_xxxxx.yyyyy" } export interface AccessToken { access_token: string; // Format: "v4.local.xxxxx" token_type: "Bearer"; expires_at: number; // Unix timestamp expires_in: number; // Seconds } export interface TokenExchangeRequest { additional_headers?: Record; ttl_seconds?: number; } export interface ServiceCredentials { apiKey: string; serviceUrl: string; } ``` -------------------------------- ### Incorrect Context Handling in Blueprint Router Source: https://github.com/tangle-network/blueprint/blob/main/crates/router/docs/with_context.md Demonstrates an incorrect way to define routes where the function returns `Router` instead of `Router<()>` after calling `with_context`. This fails because the router still indicates missing context, preventing it from being used with `BlueprintRunnerBuilder::router`. ```rust # use blueprint_sdk::{Router, extract::Context, runner::BlueprintRunner}; # #[derive(Clone)] # struct AppContext {} # // This won't work because we're returning a `Router` // i.e. we're saying we're still missing an `AppContext` fn routes(context: AppContext) -> Router { Router::new() .route("/", |_: Context| async {}) .with_context(context) } let app = routes(AppContext {}); // We can only call `BlueprintRunnerBuilder::router` with a `Router<()>` // but `app` is a `Router` # async { let config = /* ... */ # (); let env = /* ... */ # blueprint_sdk::runner::config::BlueprintEnvironment::default(); let runner = BlueprintRunner::builder(config, env).router(app); let result = runner.run().await; # }; ``` -------------------------------- ### Token Exchange API Response Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Illustrates the expected JSON response upon a successful token exchange request, containing the access token, token type, and expiration details. ```json { "access_token": "v4.local.xxxxx", "token_type": "Bearer", "expires_at": 1704067200, "expires_in": 900 } ``` -------------------------------- ### Authenticated Resource Access Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Accesses protected resources using an authenticated token. This endpoint requires a valid access token in the Authorization header. ```APIDOC ## GET /api/v1/resource ### Description Accesses protected resources using an authenticated token. This endpoint requires a valid access token in the Authorization header. ### Method GET ### Endpoint /api/v1/resource ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```http GET /api/v1/resource Authorization: Bearer v4.local.xxxxx ``` ### Response #### Success Response (200) - **[Response fields will vary based on the specific resource]** #### Response Example ```json { "data": "[resource data]" } ``` ``` -------------------------------- ### Token Exchange API Source: https://github.com/tangle-network/blueprint/blob/main/crates/auth/AUTH_WORKFLOW.md Exchanges credentials for an access token. This endpoint is used to obtain a temporary access token for authenticated requests. ```APIDOC ## POST /v1/auth/exchange ### Description Exchanges credentials for an access token. This endpoint is used to obtain a temporary access token for authenticated requests. ### Method POST ### Endpoint /v1/auth/exchange ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **additional_headers** (object) - Required - Additional headers to include in the request, such as X-Tenant-ID. - **X-Tenant-ID** (string) - Required - The ID of the tenant for which the token is being requested. - **ttl_seconds** (integer) - Required - The time-to-live for the access token in seconds. ### Request Example ```json { "additional_headers": { "X-Tenant-ID": "tenant-123" }, "ttl_seconds": 600 } ``` ### Response #### Success Response (200) - **access_token** (string) - The generated access token. - **token_type** (string) - The type of the token (e.g., 'Bearer'). - **expires_at** (integer) - The Unix timestamp when the token expires. - **expires_in** (integer) - The time in seconds until the token expires. #### Response Example ```json { "access_token": "v4.local.xxxxx", "token_type": "Bearer", "expires_at": 1704067200, "expires_in": 900 } ``` ``` -------------------------------- ### Tangle Network Broadcast Gossip Message Sequence Source: https://github.com/tangle-network/blueprint/blob/main/crates/networking/README.md Depicts the process of broadcasting a message from one node to multiple other connected nodes within the Tangle network. This utilizes a gossip protocol for message propagation. ```mermaid sequenceDiagram participant A as Node A participant B as Node B participant C as Node C participant D as Node D A->>B: Broadcast message A->>C: Broadcast message A->>D: Broadcast message ``` -------------------------------- ### Improve Job Type Error Messages with debug_job Source: https://github.com/tangle-network/blueprint/blob/main/crates/core/docs/debugging_job_type_errors.md This proc-macro helps diagnose why a function might not be implementing the `Job` trait correctly. Apply it to your job function to receive more detailed compiler errors. ```rust use blueprint_sdk::debug_job; #[debug_job] async fn my_job(input: u64) -> u64 { // Your job logic here input * 2 } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.