cotyledon 0.1.0

Framework for writing sprouts — sandboxed, event-driven on-chain trading bots.
Documentation
//! The sprout runtime context.

use serde::de::DeserializeOwned;

use crate::obs::{Log, Metric};
use crate::types::Trade;
use crate::{Result, State, Wallet, host};

/// Handle to the engine. Every method is executed by the engine on the sprout's
/// behalf; the sprout has no direct access to keys, network, or storage. Cheap
/// to copy.
#[derive(Clone, Copy)]
pub struct Ctx;

impl Ctx {
    /// Deserialize the per-deployment config (`[config]` in `sprout.toml`).
    pub fn config<T: DeserializeOwned>(&self) -> Result<T> {
        Ok(serde_json::from_slice(&host::config_raw())?)
    }

    /// Current USD price of a token.
    pub async fn price(&self, token: &str) -> Result<f64> {
        host::price(token).await
    }

    /// The sprout's wallet (signing happens in the engine).
    pub fn wallet(&self) -> Wallet {
        Wallet
    }

    /// The RPC client for submitting transactions.
    pub fn rpc(&self) -> Rpc {
        Rpc
    }

    /// Per-sprout key/value storage.
    pub fn state(&self) -> State {
        State
    }

    /// Structured logging.
    pub fn log(&self) -> Log {
        Log
    }

    /// Metrics.
    pub fn metric(&self) -> Metric {
        Metric
    }

    /// Record a trade on the sprout's activity feed.
    pub fn emit(&self, trade: Trade) {
        let bytes = serde_json::to_vec(&trade).unwrap_or_default();
        host::emit(&bytes);
    }
}

/// Submits transactions to the chain through the engine.
pub struct Rpc;

impl Rpc {
    /// Submit a signed transaction; returns its signature.
    pub async fn submit_tx(&self, signed_tx: &[u8]) -> Result<String> {
        host::submit_tx(signed_tx).await
    }
}