linera_sdk/contract/
mod.rs1mod conversions_from_wit;
7mod conversions_to_wit;
8#[cfg(not(with_testing))]
9mod runtime;
10#[cfg(with_testing)]
11mod test_runtime;
12#[doc(hidden)]
13pub mod wit;
14
15#[cfg(not(with_testing))]
16pub use self::runtime::ContractRuntime;
17#[cfg(with_testing)]
18pub use self::test_runtime::MockContractRuntime;
19#[doc(hidden)]
20pub use self::wit::export_contract;
21use crate::{log::ContractLogger, util::BlockingWait};
22
23#[cfg(with_testing)]
25pub type ContractRuntime<Application> = MockContractRuntime<Application>;
26
27#[macro_export]
33macro_rules! contract {
34 ($contract:ident) => {
35 #[doc(hidden)]
36 static mut CONTRACT: Option<$contract> = None;
37
38 $crate::export_contract!($contract with_types_in $crate::contract::wit);
40
41 impl $crate::contract::wit::exports::linera::app::contract_entrypoints::Guest
43 for $contract
44 {
45 fn instantiate(argument: Vec<u8>) {
46 use $crate::util::BlockingWait;
47 $crate::contract::run_async_entrypoint::<$contract, _, _>(
48 unsafe { &mut CONTRACT },
49 move |contract| {
50 let argument = $crate::serde_json::from_slice(&argument)
51 .unwrap_or_else(|_| panic!("Failed to deserialize instantiation argument {argument:?}"));
52
53 contract.instantiate(argument).blocking_wait()
54 },
55 )
56 }
57
58 fn execute_operation(operation: Vec<u8>) -> Vec<u8> {
59 use $crate::util::BlockingWait;
60 $crate::contract::run_async_entrypoint::<$contract, _, _>(
61 unsafe { &mut CONTRACT },
62 move |contract| {
63 let operation = <$contract as $crate::abi::ContractAbi>::deserialize_operation(operation)
64 .expect("Failed to deserialize `Operation` in execute_operation");
65
66 let response = contract.execute_operation(operation).blocking_wait();
67
68 <$contract as $crate::abi::ContractAbi>::serialize_response(response)
69 .expect("Failed to serialize `Response` in execute_operation")
70 },
71 )
72 }
73
74 fn execute_message(message: Vec<u8>) {
75 use $crate::util::BlockingWait;
76 $crate::contract::run_async_entrypoint::<$contract, _, _>(
77 unsafe { &mut CONTRACT },
78 move |contract| {
79 let message: <$contract as $crate::Contract>::Message =
80 $crate::bcs::from_bytes(&message)
81 .expect("Failed to deserialize message");
82
83 contract.execute_message(message).blocking_wait()
84 },
85 )
86 }
87
88 fn process_streams(updates: Vec<
89 $crate::contract::wit::exports::linera::app::contract_entrypoints::StreamUpdate,
90 >) {
91 use $crate::util::BlockingWait;
92 $crate::contract::run_async_entrypoint::<$contract, _, _>(
93 unsafe { &mut CONTRACT },
94 move |contract| {
95 let updates = updates.into_iter().map(Into::into).collect();
96 contract.process_streams(updates).blocking_wait()
97 },
98 )
99 }
100
101 fn finalize() {
102 use $crate::util::BlockingWait;
103
104 let contract = unsafe { CONTRACT.take() }
105 .expect("Calling `store` on a `Contract` instance that wasn't loaded");
106
107 contract.store().blocking_wait();
108 }
109 }
110
111 #[cfg(not(target_arch = "wasm32"))]
114 fn main() {}
115 };
116}
117
118pub fn run_async_entrypoint<Contract, Output, RawOutput>(
121 contract: &mut Option<Contract>,
122 entrypoint: impl FnOnce(&mut Contract) -> Output + Send,
123) -> RawOutput
124where
125 Contract: crate::Contract,
126 Output: Into<RawOutput> + Send + 'static,
127{
128 ContractLogger::install();
129
130 let contract =
131 contract.get_or_insert_with(|| Contract::load(ContractRuntime::new()).blocking_wait());
132
133 entrypoint(contract).into()
134}