1#![allow(clippy::too_many_arguments)]
17
18pub mod bindings {
20 wit_bindgen::generate!({
21 path: "wit",
22 world: "agent",
23 async: [
26 "shonin:agent/drivers@0.1.0#submit",
27 "shonin:agent/drivers@0.1.0#account-state",
28 "shonin:agent/transfers@0.1.0#move",
29 "shonin:agent/transfers@0.1.0#bridge",
30 "shonin:agent/transfers@0.1.0#balances",
31 "shonin:agent/data@0.1.0#query",
32 "shonin:agent/websocket@0.1.0#connect",
33 "shonin:agent/websocket@0.1.0#[method]connection.send",
34 "shonin:agent/inference@0.1.0#infer",
35 "run",
36 ],
37 generate_all,
40 pub_export_macro: true,
41 default_bindings_module: "strategy_sdk::bindings",
42 });
43}
44
45#[cfg(feature = "hyperliquid")]
46pub mod hyperliquid;
47#[cfg(feature = "lighter")]
48pub mod lighter;
49pub mod local;
50#[cfg(feature = "orca")]
51pub mod orca;
52pub mod payload;
53#[cfg(feature = "robinhood")]
54pub mod robinhood;
55pub mod sizing;
56pub mod state;
57pub mod streams;
58
59pub use bindings::Guest as Agent;
60pub use bindings::shonin::agent::types::Verdict;
61pub use bindings::shonin::agent::{
62 data, drivers, inference, secrets, transfers, types, vault, websocket,
63};
64pub use bindings::wasi::http;
67pub use bindings::wasi::keyvalue;
71pub use local::{
72 AccountEvent, AccountState, Action, MarketState, Order, PositionState, Query, Receipt, Side,
73};
74pub use payload::{Decimal, decimal, from_payload, millionths, to_payload};
75pub use sizing::{Limits, size_for};
76
77pub const VERSION: &str = env!("CARGO_PKG_VERSION");
81
82#[macro_export]
92macro_rules! export_agent {
93 ($name:ident) => {
94 $crate::bindings::export!($name with_types_in $crate::bindings);
95 };
96}
97
98impl bindings::shonin::agent::vault::Claim {
99 pub const WHOLE: u64 = 1_000_000_000_000_000_000;
102
103 pub fn share(&self) -> Decimal {
106 Decimal::from(self.fraction) / Decimal::from(Self::WHOLE)
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use bindings::shonin::agent::vault::Claim;
114
115 #[test]
116 fn a_claim_s_fraction_reads_as_a_share_of_the_whole_vault() {
117 let quarter = Claim {
118 id: 3,
119 fraction: Claim::WHOLE / 4,
120 };
121 assert_eq!(quarter.share(), decimal("0.25"));
122 let whole = Claim {
123 id: 4,
124 fraction: Claim::WHOLE,
125 };
126 assert_eq!(whole.share(), decimal("1"));
127 }
128
129 #[test]
130 fn a_feed_and_its_values_read_back_as_they_were_written() {
131 use streams::{Book, HyperliquidFeed, HyperliquidValue, Level};
132 let feed = HyperliquidFeed::Book {
133 coin: "BTC".to_string(),
134 };
135 assert_eq!(
136 from_payload::<HyperliquidFeed>(&to_payload(&feed)),
137 Ok(feed)
138 );
139 let value = HyperliquidValue::Book(Book {
140 market: "BTC".to_string(),
141 bids: vec![Level {
142 price: decimal("64000.5"),
143 size: decimal("0.1"),
144 orders: Some(2),
145 }],
146 asks: Vec::new(),
147 });
148 assert_eq!(
149 from_payload::<HyperliquidValue>(&to_payload(&value)),
150 Ok(value)
151 );
152 }
153}