loop-agent-sdk 0.1.0

Trustless agent SDK for Loop Protocol — intent-based execution on Solana.
Documentation
//! # Loop Agent SDK
//! 
//! Trustless agent infrastructure for the Loop Protocol.
//! 
//! ## Architecture
//! 
//! ```text
//! ┌─────────────────────────────────────────────────────────┐
//! │                    LOOP AGENT SDK                       │
//! ├─────────────────┬─────────────────┬─────────────────────┤
//! │     STATE       │     ACTION      │     PERCEPTION      │
//! │                 │                 │                     │
//! │ context_fetch   │ capture_value   │ on_transaction      │
//! │ context_push    │ stake_cred      │ on_location_hit     │
//! │ agent_memory    │ claim_yield     │ on_proof_submitted  │
//! │                 │ optimize_yield  │ on_position_unlock  │
//! └─────────────────┴─────────────────┴─────────────────────┘
//! ```
//! 
//! ## Security Model
//! 
//! - **Intent-Based Execution**: Agents request actions, smart contracts execute
//! - **Session Keys**: Scoped permissions with TTL (read/capture/stake)
//! - **Trustless Distribution**: 80/14/6 split enforced by contract, not agent
//! - **No Key Access**: Agents never hold private keys or move funds directly
//! 
//! ## MCP Compliance
//! 
//! This SDK is designed to be MCP (Model Context Protocol) compliant.
//! See `mcp/loop-vault-manifest.json` for the tool/resource definitions
//! that allow any MCP-compatible AI to interact with Loop vaults.
//! 
//! ## Quick Start
//! 
//! ```rust,ignore
//! use loop_agent_sdk::{
//!     action::{VaultAction, SessionKey, ZkProof},
//!     perception::{PerceptionEvent, PerceptionHandler},
//!     state::{StateStore, UserContext},
//! };
//! 
//! // In your Lambda handler:
//! async fn handler(event: PerceptionEvent) -> Result<(), Error> {
//!     // 1. Load user context (<100ms)
//!     let ctx = state_store.context_fetch(&event.user_pubkey())?;
//!     
//!     // 2. Get session key for this user
//!     let session = get_session_key(&ctx.pubkey).await?;
//!     
//!     // 3. Execute action based on event
//!     match event {
//!         PerceptionEvent::TransactionDetected(tx) => {
//!             let proof = build_proof_from_pos(&tx)?;
//!             let result = vault.capture_value(&session, tx.merchant_id, proof)?;
//!             
//!             // 4. Update context
//!             state_store.push_event(&ctx.pubkey, ContextEvent {
//!                 event_type: "capture".into(),
//!                 amount: Some(result.cred_minted),
//!                 ..
//!             })?;
//!         }
//!         // ... handle other events
//!     }
//!     
//!     Ok(())
//! }
//! ```

pub mod action;
pub mod constants;
#[cfg(feature = "dynamodb")]
pub mod dynamo;
pub mod gateway;
#[cfg(feature = "notifications")]
pub mod notifications;
pub mod perception;
#[cfg(feature = "privacy")]
pub mod privacy;
pub mod reputation_engine;
pub mod state;
#[cfg(feature = "supabase")]
pub mod supabase;
pub mod vault_action;
#[cfg(feature = "webhook")]
pub mod webhook;

// Re-export lambda_runtime for binaries
#[cfg(feature = "lambda")]
pub use aws_lambda_runtime as lambda_runtime;

// Re-exports for convenience
pub use action::{
    VaultAction, SessionKey, PermissionScope, ZkProof, ProofType,
    CaptureResult, StakingPosition, YieldRecommendation, ActionError,
    DISTRIBUTION, YIELD_RATES_BPS,
};

pub use perception::{
    PerceptionEvent, PerceptionHandler, PerceptionError,
    TransactionEvent, LocationEvent, ProofEvent, UnlockEvent,
    Processor, GeoEventType,
};

pub use state::{
    StateStore, StateError, UserContext, VaultState,
    UserPreferences, ContextEvent, init_user_context,
};

pub use vault_action::SolanaVaultAction;

#[cfg(feature = "dynamodb")]
pub use dynamo::{
    DynamoStateStore, DynamoConfig, CardMapping, PendingCapture, SessionKeyData,
    create_table,
};

#[cfg(feature = "privacy")]
pub use privacy::{
    PrivacyLayer, PrivacyConfig, LoopFingerprint, PrivacyError,
    generate_pepper, create_pepper_secret,
};

#[cfg(feature = "webhook")]
pub use webhook::{
    WebhookHandler, WebhookSecrets, FidelSecrets, WebhookContext,
    WebhookSource, WebhookError, NormalizedTransaction, TransactionType,
    verify_fidel_signature, verify_square_signature, verify_stripe_signature,
    parse_fidel_webhook, parse_square_webhook,
};

#[cfg(feature = "notifications")]
pub use notifications::{
    NotificationService, NotificationConfig, NotificationError,
    PushNotification, NotificationData, NotificationPriority, NotificationResult,
};

#[cfg(feature = "supabase")]
pub use supabase::{
    SupabaseClient, SupabaseConfig, SupabaseAttestation, SupabaseReputationScore,
};

pub use constants::{
    Network, ProgramIds, TokenMints, MainnetState,
    CaptureType, PermissionLevel, EscrowStatus, AgentType, AgentStatus,
    CRED_DECIMALS, OXO_DECIMALS, LAMPORTS_PER_CRED, LAMPORTS_PER_OXO,
    USER_SHARE_BPS, TREASURY_SHARE_BPS, STAKER_SHARE_BPS,
    STAKING_APY, MIN_STAKE_DAYS, MAX_STAKE_DAYS,
    rpc_endpoint, DEVNET_RPC, MAINNET_RPC,
    STAKE_30D_APY_BPS, STAKE_90D_APY_BPS, STAKE_180D_APY_BPS, STAKE_365D_APY_BPS,
    SESSION_KEY_TTL_HOURS, SESSION_KEY_MAX_ACTIONS, CONTEXT_RELOAD_TARGET_MS,
};

// Reputation Engine for 22-Layer Stack
pub use reputation_engine::{
    ReputationEngine, TrustScore, TrustTier, CaptureLayer, LayerGroup,
    Attestation, AttestationRecord, AttestationMetadata, VaultAttestation, VaultAction as VaultAttestAction,
    ReputationDimension, ReputationResponse, ReputationCapabilities, LayerActivity,
    // VPA (Verified Professional Attestation) - industry agnostic
    ProfessionalAttestation, CredentialCategory, DifficultyTier, VerificationLevel,
    SWARM_COORDINATOR_THRESHOLD, COLLATERAL_THRESHOLD, MAX_SCORE,
};

// A2A Gateway with reputation-based access control
pub use gateway::{
    Gateway, GatewayError, A2ARequest, A2AResponse, SwarmAction, PermissionCheck,
};

/// SDK version
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Utility functions
pub mod utils {
    use super::constants::LAMPORTS_PER_CRED;
    
    /// Convert lamports to Cred (human readable)
    pub fn lamports_to_cred(lamports: u64) -> f64 {
        lamports as f64 / LAMPORTS_PER_CRED as f64
    }
    
    /// Convert Cred to lamports
    pub fn cred_to_lamports(cred: f64) -> u64 {
        (cred * LAMPORTS_PER_CRED as f64) as u64
    }
    
    /// Calculate yield for a position
    pub fn calculate_yield(
        principal: u64,
        apy_bps: u16,
        days: u16,
    ) -> u64 {
        let daily_rate = apy_bps as f64 / 10000.0 / 365.0;
        let multiplier = (1.0 + daily_rate).powi(days as i32);
        let final_amount = principal as f64 * multiplier;
        (final_amount - principal as f64) as u64
    }
    
    /// Calculate distribution split
    pub fn calculate_split(total: u64) -> (u64, u64, u64) {
        let user = (total as u128 * 8000 / 10000) as u64;
        let treasury = (total as u128 * 1400 / 10000) as u64;
        let stakers = total - user - treasury;  // Remainder to avoid rounding loss
        (user, treasury, stakers)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn lamport_conversion_roundtrip() {
        let cred = 42.5;
        let lamports = utils::cred_to_lamports(cred);
        let back = utils::lamports_to_cred(lamports);
        assert!((back - cred).abs() < 0.000001);
    }
    
    #[test]
    fn split_adds_up() {
        let total = 1_000_000_000u64;  // 1 Cred
        let (user, treasury, stakers) = utils::calculate_split(total);
        assert_eq!(user + treasury + stakers, total);
        assert_eq!(user, 800_000_000);      // 80%
        assert_eq!(treasury, 140_000_000);  // 14%
        assert_eq!(stakers, 60_000_000);    // 6%
    }
    
    #[test]
    fn yield_calculation() {
        let principal = 1_000_000_000_000u64;  // 1000 Cred
        let yield_amount = utils::calculate_yield(principal, 1200, 90); // 12% APY, 90 days
        // ~29 Cred yield expected
        assert!(yield_amount > 28_000_000_000);
        assert!(yield_amount < 32_000_000_000);
    }
}