Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"crates/nexum-engine",
"crates/shepherd-sdk",
"modules/ethflow-watcher",
"modules/example",
"modules/twap-monitor",
Expand Down
19 changes: 19 additions & 0 deletions crates/shepherd-sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "shepherd-sdk"
version = "0.1.0"
edition.workspace = true
license.workspace = true
repository.workspace = true
description = "Guest-side SDK for Shepherd modules: re-exports, helpers, and prelude on top of cowprotocol + alloy types."

[lib]
# Plain library — modules link this and emit their own cdylib for the
# WASM Component. Building shepherd-sdk on the host target is also
# supported so the helpers are unit-testable without a wasm toolchain.

[dependencies]
cowprotocol = { version = "1.0.0-alpha.3", default-features = false }
alloy-primitives = { version = "1.6", default-features = false, features = ["std", "serde"] }
alloy-sol-types = { version = "1.5", default-features = false, features = ["std"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", default-features = false, features = ["alloc"] }
99 changes: 99 additions & 0 deletions crates/shepherd-sdk/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! # shepherd-sdk
//!
//! Guest-side SDK for Shepherd modules. The crate is the shared
//! companion to the per-module `wit_bindgen::generate!` invocation:
//! modules keep their own wit-bindgen call (which emits the world-
//! specific `Guest` trait, `HostError` shape, and host import shims
//! into the module's own crate) and pull helpers + canonical
//! primitive types from here.
//!
//! ## What lives here
//!
//! - [`prelude`] — `use shepherd_sdk::prelude::*` imports the
//! protocol-level types modules need on every other line: alloy
//! primitives ([`Address`](alloy_primitives::Address),
//! [`B256`](alloy_primitives::B256),
//! [`Bytes`](alloy_primitives::Bytes),
//! [`U256`](alloy_primitives::U256), [`keccak256`](
//! alloy_primitives::keccak256)) and cowprotocol's order /
//! signing surface ([`OrderCreation`](cowprotocol::OrderCreation),
//! [`OrderData`](cowprotocol::OrderData),
//! [`OrderUid`](cowprotocol::OrderUid),
//! [`OrderKind`](cowprotocol::OrderKind),
//! [`Signature`](cowprotocol::Signature),
//! [`Chain`](cowprotocol::Chain),
//! [`GPv2OrderData`](cowprotocol::GPv2OrderData),
//! [`EMPTY_APP_DATA_JSON`](cowprotocol::EMPTY_APP_DATA_JSON), and
//! the [`ApiError`](cowprotocol::ApiError) +
//! [`OrderPostErrorKind`](cowprotocol::error::OrderPostErrorKind)
//! retry contract).
//!
//! - [`cow`] (BLEU-840) — `GPv2OrderData` <-> `OrderData` bridging,
//! `IConditionalOrder` revert decoding, `RetryAction` classifier.
//! Stubbed in this skeleton; populated by the BLEU-840 extraction.
//!
//! - [`chain`] (BLEU-840) — `eth_call` JSON plumbing
//! (`eth_call_params`, `parse_eth_call_result`, `decode_revert_hex`).
//! Stubbed in this skeleton; populated by the BLEU-840 extraction.
//!
//! - [`store`] (BLEU-840) — `WatchSet` and `BackoffLedger` helpers
//! per ADR-0006. Stubbed in this skeleton.
//!
//! ## Why no `wit_bindgen::generate!` here
//!
//! The macro emits types into the calling crate (the module's
//! cdylib). Re-exporting wit-bindgen output from a library crate
//! would duplicate symbols and break the component-export contract.
//! Helpers in this SDK therefore take primitive types (`&[u8]`,
//! `Option<&str>`, slices) rather than the per-module `HostError`
//! struct; modules unpack their `HostError` on the way in. Trade-off
//! documented in ADR-0006 / ADR-0007 — the SDK stays on the guest
//! side, neutral to which world the module exports.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

pub mod prelude;

/// CoW Protocol bridging: `GPv2OrderData` <-> typed `OrderData`,
/// `IConditionalOrder` revert decoding, retry classification.
///
/// Skeleton — populated by [BLEU-840](
/// https://linear.app/bleu-builders/issue/BLEU-840).
pub mod cow {}

/// `eth_call` JSON plumbing: build the `[{to, data}, "latest"]`
/// params object, parse the `"0x..."` hex result, decode revert
/// payloads from the host's structured error data.
///
/// Skeleton — populated by [BLEU-840](
/// https://linear.app/bleu-builders/issue/BLEU-840).
pub mod chain {}

/// `local-store` helpers: `WatchSet`, `BackoffLedger` per ADR-0006.
///
/// Skeleton — populated by [BLEU-840](
/// https://linear.app/bleu-builders/issue/BLEU-840).
pub mod store {}

#[cfg(test)]
mod tests {
//! The skeleton has no behaviour to exercise; this test just
//! locks the prelude's surface — the build itself proves the
//! re-exports compile against both `wasm32-wasip2` and the
//! host target.

use crate::prelude::*;

#[test]
fn prelude_re_exports_resolve() {
let _addr: Address = Address::ZERO;
let _hash: B256 = B256::ZERO;
let _amt: U256 = U256::ZERO;
let _empty: Bytes = Bytes::new();
// cowprotocol re-exports
let _kind: OrderKind = OrderKind::Sell;
let _chain: Chain = Chain::Sepolia;
assert_eq!(EMPTY_APP_DATA_JSON, "{}");
}
}
38 changes: 38 additions & 0 deletions crates/shepherd-sdk/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! Bulk-imports the protocol primitives every Shepherd module uses on
//! every other line. `use shepherd_sdk::prelude::*` is a one-liner that
//! covers alloy address / hash / numeric types plus cowprotocol's
//! order, signing, and orderbook-error surface.
//!
//! The wit-bindgen-generated types (`Guest`, `HostError`, `Event`, …)
//! are **not** re-exported here because they live in each module's own
//! crate (one `wit_bindgen::generate!` call per cdylib). The prelude
//! covers only the host-neutral protocol layer that the SDK helpers
//! consume by value.

pub use alloy_primitives::{Address, B256, Bytes, U256, address, b256, hex, keccak256};

pub use cowprotocol::{
// App-data + chain + domain identity.
Chain,
DomainSeparator,
EMPTY_APP_DATA_HASH,
EMPTY_APP_DATA_JSON,
// Settlement primitives carried in event payloads and order bodies.
GPv2OrderData,
// Orderbook submission body + the parts every assembly path touches.
OrderCreation,
OrderData,
OrderKind,
// Order identity.
OrderUid,
SellTokenSource,
BuyTokenDestination,
// Signing.
Signature,
SigningScheme,
};

/// Re-exported `ApiError` typed error surface from the orderbook —
/// guest-side helpers (BLEU-840) read this back out of host-error JSON
/// to drive the `RetryAction` dispatch.
pub use cowprotocol::error::{ApiError, OrderPostErrorKind};