1use flatbuffers::WIPOffset;
2use std::borrow::Cow;
3use std::fmt::Display;
4use std::net::SocketAddr;
5
6use serde::{de::DeserializeOwned, Deserialize, Serialize};
7
8use crate::client_api::TryFromFbs;
9use crate::generated::client_request::{
10 root_as_client_request, ClientRequestType, ContractRequest as FbsContractRequest,
11 ContractRequestType, DelegateRequest as FbsDelegateRequest, DelegateRequestType,
12};
13
14use crate::delegate_interface::DelegateContext;
15use crate::generated::common::{
16 ApplicationMessage as FbsApplicationMessage, ApplicationMessageArgs, ContractCode,
17 ContractCodeArgs, ContractContainer as FbsContractContainer, ContractContainerArgs,
18 ContractInstanceId, ContractInstanceIdArgs, ContractKey as FbsContractKey, ContractKeyArgs,
19 ContractType, DeltaUpdate, DeltaUpdateArgs, GetSecretRequest as FbsGetSecretRequest,
20 GetSecretRequestArgs, GetSecretResponse as FbsGetSecretResponse, GetSecretResponseArgs,
21 RelatedDeltaUpdate, RelatedDeltaUpdateArgs, RelatedStateAndDeltaUpdate,
22 RelatedStateAndDeltaUpdateArgs, RelatedStateUpdate, RelatedStateUpdateArgs,
23 SecretsId as FbsSecretsId, SecretsIdArgs, StateAndDeltaUpdate, StateAndDeltaUpdateArgs,
24 StateUpdate, StateUpdateArgs, UpdateData as FbsUpdateData, UpdateDataArgs, UpdateDataType,
25 WasmContractV1, WasmContractV1Args,
26};
27use crate::generated::host_response::{
28 finish_host_response_buffer, ClientResponse as FbsClientResponse, ClientResponseArgs,
29 ContextUpdated as FbsContextUpdated, ContextUpdatedArgs,
30 ContractResponse as FbsContractResponse, ContractResponseArgs, ContractResponseType,
31 DelegateKey as FbsDelegateKey, DelegateKeyArgs, DelegateResponse as FbsDelegateResponse,
32 DelegateResponseArgs, GetResponse as FbsGetResponse, GetResponseArgs,
33 HostResponse as FbsHostResponse, HostResponseArgs, HostResponseType, Ok as FbsOk, OkArgs,
34 OutboundDelegateMsg as FbsOutboundDelegateMsg, OutboundDelegateMsgArgs,
35 OutboundDelegateMsgType, PutResponse as FbsPutResponse, PutResponseArgs,
36 RequestUserInput as FbsRequestUserInput, RequestUserInputArgs,
37 SetSecretRequest as FbsSetSecretRequest, SetSecretRequestArgs,
38 UpdateNotification as FbsUpdateNotification, UpdateNotificationArgs,
39 UpdateResponse as FbsUpdateResponse, UpdateResponseArgs,
40};
41use crate::prelude::ContractContainer::Wasm;
42use crate::prelude::ContractWasmAPIVersion::V1;
43use crate::prelude::UpdateData::{
44 Delta, RelatedDelta, RelatedState, RelatedStateAndDelta, State, StateAndDelta,
45};
46use crate::{
47 delegate_interface::{DelegateKey, InboundDelegateMsg, OutboundDelegateMsg},
48 prelude::{
49 ContractKey, DelegateContainer, GetSecretRequest, Parameters, RelatedContracts, SecretsId,
50 StateSummary, UpdateData, WrappedState,
51 },
52 versioning::ContractContainer,
53};
54
55use super::WsApiError;
56
57#[derive(Debug, Serialize, Deserialize)]
58pub struct ClientError {
59 kind: Box<ErrorKind>,
60}
61
62impl ClientError {
63 pub fn into_fbs_bytes(self) -> Result<Vec<u8>, Box<ClientError>> {
64 use crate::generated::host_response::{Error, ErrorArgs};
65 let mut builder = flatbuffers::FlatBufferBuilder::new();
66 let msg_offset = builder.create_string(&self.to_string());
67 let err_offset = Error::create(
68 &mut builder,
69 &ErrorArgs {
70 msg: Some(msg_offset),
71 },
72 );
73 let host_response_offset = FbsHostResponse::create(
74 &mut builder,
75 &HostResponseArgs {
76 response_type: HostResponseType::Ok,
77 response: Some(err_offset.as_union_value()),
78 },
79 );
80 finish_host_response_buffer(&mut builder, host_response_offset);
81 Ok(builder.finished_data().to_vec())
82 }
83
84 pub fn kind(&self) -> &ErrorKind {
85 &self.kind
86 }
87}
88
89impl From<ErrorKind> for ClientError {
90 fn from(kind: ErrorKind) -> Self {
91 ClientError {
92 kind: Box::new(kind),
93 }
94 }
95}
96
97impl<T: Into<Cow<'static, str>>> From<T> for ClientError {
98 fn from(cause: T) -> Self {
99 ClientError {
100 kind: Box::new(ErrorKind::Unhandled {
101 cause: cause.into(),
102 }),
103 }
104 }
105}
106
107#[derive(thiserror::Error, Debug, Serialize, Deserialize, Clone)]
108#[non_exhaustive]
109pub enum ErrorKind {
110 #[error("comm channel between client/host closed")]
111 ChannelClosed,
112 #[error("error while deserializing: {cause}")]
113 DeserializationError { cause: Cow<'static, str> },
114 #[error("client disconnected")]
115 Disconnect,
116 #[error("failed while trying to unpack state for {0}")]
117 IncorrectState(ContractKey),
118 #[error("node not available")]
119 NodeUnavailable,
120 #[error("lost the connection with the protocol handling connections")]
121 TransportProtocolDisconnect,
122 #[error("unhandled error: {cause}")]
123 Unhandled { cause: Cow<'static, str> },
124 #[error("unknown client id: {0}")]
125 UnknownClient(usize),
126 #[error(transparent)]
127 RequestError(#[from] RequestError),
128 #[error("error while executing operation in the network: {cause}")]
129 OperationError { cause: Cow<'static, str> },
130 #[error("operation timed out")]
132 FailedOperation,
133 #[error("peer should shutdown")]
134 Shutdown,
135}
136
137impl Display for ClientError {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(f, "client error: {}", self.kind)
140 }
141}
142
143impl std::error::Error for ClientError {}
144
145#[derive(Debug, thiserror::Error, Serialize, Deserialize, Clone)]
146#[non_exhaustive]
147pub enum RequestError {
148 #[error(transparent)]
149 ContractError(#[from] ContractError),
150 #[error(transparent)]
151 DelegateError(#[from] DelegateError),
152 #[error("client disconnect")]
153 Disconnect,
154 #[error("operation timed out")]
155 Timeout,
156}
157
158#[derive(Debug, thiserror::Error, Serialize, Deserialize, Clone)]
160#[non_exhaustive]
161pub enum DelegateError {
162 #[error("error while registering delegate {0}")]
163 RegisterError(DelegateKey),
164 #[error("execution error, cause {0}")]
165 ExecutionError(Cow<'static, str>),
166 #[error("missing delegate {0}")]
167 Missing(DelegateKey),
168 #[error("missing secret `{secret}` for delegate {key}")]
169 MissingSecret { key: DelegateKey, secret: SecretsId },
170 #[error("forbidden access to secret: {0}")]
171 ForbiddenSecretAccess(SecretsId),
172}
173
174#[derive(Debug, thiserror::Error, Serialize, Deserialize, Clone)]
176#[non_exhaustive]
177pub enum ContractError {
178 #[error("failed to get contract {key}, reason: {cause}")]
179 Get {
180 key: ContractKey,
181 cause: Cow<'static, str>,
182 },
183 #[error("put error for contract {key}, reason: {cause}")]
184 Put {
185 key: ContractKey,
186 cause: Cow<'static, str>,
187 },
188 #[error("update error for contract {key}, reason: {cause}")]
189 Update {
190 key: ContractKey,
191 cause: Cow<'static, str>,
192 },
193 #[error("failed to subscribe for contract {key}, reason: {cause}")]
194 Subscribe {
195 key: ContractKey,
196 cause: Cow<'static, str>,
197 },
198 #[error("dependency contract stack overflow : {key}")]
200 ContractStackOverflow {
201 key: crate::contract_interface::ContractInstanceId,
202 },
203 #[error("missing related contract: {key}")]
204 MissingRelated {
205 key: crate::contract_interface::ContractInstanceId,
206 },
207 #[error("missing contract: {key}")]
208 MissingContract {
209 key: crate::contract_interface::ContractInstanceId,
210 },
211}
212
213impl ContractError {
214 const EXECUTION_ERROR: &'static str = "execution error";
215 const INVALID_PUT: &'static str = "invalid put";
216
217 pub fn update_exec_error(key: ContractKey, additional_info: impl std::fmt::Display) -> Self {
218 Self::Update {
219 key,
220 cause: format!(
221 "{exec_err}: {additional_info}",
222 exec_err = Self::EXECUTION_ERROR
223 )
224 .into(),
225 }
226 }
227
228 pub fn invalid_put(key: ContractKey) -> Self {
229 Self::Put {
230 key,
231 cause: Self::INVALID_PUT.into(),
232 }
233 }
234
235 pub fn invalid_update(key: ContractKey) -> Self {
236 Self::Update {
237 key,
238 cause: Self::INVALID_PUT.into(),
239 }
240 }
241}
242
243#[derive(Serialize, Deserialize, Debug, Clone)]
245#[non_exhaustive]
246pub enum ClientRequest<'a> {
248 DelegateOp(#[serde(borrow)] DelegateRequest<'a>),
249 ContractOp(#[serde(borrow)] ContractRequest<'a>),
250 Disconnect {
251 cause: Option<Cow<'static, str>>,
252 },
253 Authenticate {
254 token: String,
255 },
256 NodeQueries(ConnectedPeers),
257 Close,
259}
260
261#[derive(Serialize, Deserialize, Debug, Clone)]
262pub struct ConnectedPeers {}
263
264impl ClientRequest<'_> {
265 pub fn into_owned(self) -> ClientRequest<'static> {
266 match self {
267 ClientRequest::ContractOp(op) => {
268 let owned = match op {
269 ContractRequest::Put {
270 contract,
271 state,
272 related_contracts,
273 subscribe,
274 } => {
275 let related_contracts = related_contracts.into_owned();
276 ContractRequest::Put {
277 contract,
278 state,
279 related_contracts,
280 subscribe,
281 }
282 }
283 ContractRequest::Update { key, data } => {
284 let data = data.into_owned();
285 ContractRequest::Update { key, data }
286 }
287 ContractRequest::Get {
288 key,
289 return_contract_code,
290 subscribe,
291 } => ContractRequest::Get {
292 key,
293 return_contract_code,
294 subscribe,
295 },
296 ContractRequest::Subscribe { key, summary } => ContractRequest::Subscribe {
297 key,
298 summary: summary.map(StateSummary::into_owned),
299 },
300 };
301 owned.into()
302 }
303 ClientRequest::DelegateOp(op) => {
304 let op = op.into_owned();
305 ClientRequest::DelegateOp(op)
306 }
307 ClientRequest::Disconnect { cause } => ClientRequest::Disconnect { cause },
308 ClientRequest::Authenticate { token } => ClientRequest::Authenticate { token },
309 ClientRequest::NodeQueries(query) => ClientRequest::NodeQueries(query),
310 ClientRequest::Close => ClientRequest::Close,
311 }
312 }
313
314 pub fn is_disconnect(&self) -> bool {
315 matches!(self, Self::Disconnect { .. })
316 }
317
318 pub fn try_decode_fbs(msg: &[u8]) -> Result<ClientRequest, WsApiError> {
319 let req = {
320 match root_as_client_request(msg) {
321 Ok(client_request) => match client_request.client_request_type() {
322 ClientRequestType::ContractRequest => {
323 let contract_request =
324 client_request.client_request_as_contract_request().unwrap();
325 ContractRequest::try_decode_fbs(&contract_request)?.into()
326 }
327 ClientRequestType::DelegateRequest => {
328 let delegate_request =
329 client_request.client_request_as_delegate_request().unwrap();
330 DelegateRequest::try_decode_fbs(&delegate_request)?.into()
331 }
332 ClientRequestType::Disconnect => {
333 let delegate_request =
334 client_request.client_request_as_disconnect().unwrap();
335 let cause = delegate_request
336 .cause()
337 .map(|cause_msg| cause_msg.to_string().into());
338 ClientRequest::Disconnect { cause }
339 }
340 ClientRequestType::Authenticate => {
341 let auth_req = client_request.client_request_as_authenticate().unwrap();
342 let token = auth_req.token();
343 ClientRequest::Authenticate {
344 token: token.to_owned(),
345 }
346 }
347 _ => unreachable!(),
348 },
349 Err(e) => {
350 let cause = format!("{e}");
351 return Err(WsApiError::deserialization(cause));
352 }
353 }
354 };
355
356 Ok(req)
357 }
358}
359
360#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
361#[non_exhaustive]
362pub enum ContractRequest<'a> {
363 Put {
365 contract: ContractContainer,
366 state: WrappedState,
368 #[serde(borrow)]
370 related_contracts: RelatedContracts<'a>,
371 subscribe: bool,
373 },
374 Update {
376 key: ContractKey,
377 #[serde(borrow)]
378 data: UpdateData<'a>,
379 },
380 Get {
382 key: ContractKey,
384 return_contract_code: bool,
386 subscribe: bool,
388 },
389 Subscribe {
392 key: ContractKey,
393 summary: Option<StateSummary<'a>>,
394 },
395}
396
397impl ContractRequest<'_> {
398 pub fn into_owned(self) -> ContractRequest<'static> {
399 match self {
400 Self::Put {
401 contract,
402 state,
403 related_contracts,
404 subscribe,
405 } => ContractRequest::Put {
406 contract,
407 state,
408 related_contracts: related_contracts.into_owned(),
409 subscribe,
410 },
411 Self::Update { key, data } => ContractRequest::Update {
412 key,
413 data: data.into_owned(),
414 },
415 Self::Get {
416 key,
417 return_contract_code: fetch_contract,
418 subscribe,
419 } => ContractRequest::Get {
420 key,
421 return_contract_code: fetch_contract,
422 subscribe,
423 },
424 Self::Subscribe { key, summary } => ContractRequest::Subscribe {
425 key,
426 summary: summary.map(StateSummary::into_owned),
427 },
428 }
429 }
430}
431
432impl<'a> From<ContractRequest<'a>> for ClientRequest<'a> {
433 fn from(op: ContractRequest<'a>) -> Self {
434 ClientRequest::ContractOp(op)
435 }
436}
437
438impl<'a> TryFromFbs<&FbsContractRequest<'a>> for ContractRequest<'a> {
440 fn try_decode_fbs(request: &FbsContractRequest<'a>) -> Result<Self, WsApiError> {
441 let req = {
442 match request.contract_request_type() {
443 ContractRequestType::Get => {
444 let get = request.contract_request_as_get().unwrap();
445 let key = ContractKey::try_decode_fbs(&get.key())?;
446 let fetch_contract = get.fetch_contract();
447 let subscribe = get.subscribe();
448 ContractRequest::Get {
449 key,
450 return_contract_code: fetch_contract,
451 subscribe,
452 }
453 }
454 ContractRequestType::Put => {
455 let put = request.contract_request_as_put().unwrap();
456 let contract = ContractContainer::try_decode_fbs(&put.container())?;
457 let state = WrappedState::new(put.wrapped_state().bytes().to_vec());
458 let related_contracts =
459 RelatedContracts::try_decode_fbs(&put.related_contracts())?.into_owned();
460 let subscribe = put.subscribe();
461 ContractRequest::Put {
462 contract,
463 state,
464 related_contracts,
465 subscribe,
466 }
467 }
468 ContractRequestType::Update => {
469 let update = request.contract_request_as_update().unwrap();
470 let key = ContractKey::try_decode_fbs(&update.key())?;
471 let data = UpdateData::try_decode_fbs(&update.data())?.into_owned();
472 ContractRequest::Update { key, data }
473 }
474 ContractRequestType::Subscribe => {
475 let subscribe = request.contract_request_as_subscribe().unwrap();
476 let key = ContractKey::try_decode_fbs(&subscribe.key())?;
477 let summary = subscribe
478 .summary()
479 .map(|summary_data| StateSummary::from(summary_data.bytes()));
480 ContractRequest::Subscribe { key, summary }
481 }
482 _ => unreachable!(),
483 }
484 };
485
486 Ok(req)
487 }
488}
489
490impl<'a> From<DelegateRequest<'a>> for ClientRequest<'a> {
491 fn from(op: DelegateRequest<'a>) -> Self {
492 ClientRequest::DelegateOp(op)
493 }
494}
495
496#[derive(Serialize, Deserialize, Debug, Clone)]
497#[non_exhaustive]
498pub enum DelegateRequest<'a> {
499 ApplicationMessages {
500 key: DelegateKey,
501 #[serde(deserialize_with = "Parameters::deser_params")]
502 params: Parameters<'a>,
503 #[serde(borrow)]
504 inbound: Vec<InboundDelegateMsg<'a>>,
505 },
506 GetSecretRequest {
507 key: DelegateKey,
508 #[serde(borrow)]
509 params: Parameters<'a>,
510 get_request: GetSecretRequest,
511 },
512 RegisterDelegate {
513 delegate: DelegateContainer,
514 cipher: [u8; 32],
515 nonce: [u8; 24],
516 },
517 UnregisterDelegate(DelegateKey),
518}
519
520impl DelegateRequest<'_> {
521 pub const DEFAULT_CIPHER: [u8; 32] = [
522 0, 24, 22, 150, 112, 207, 24, 65, 182, 161, 169, 227, 66, 182, 237, 215, 206, 164, 58, 161,
523 64, 108, 157, 195, 0, 0, 0, 0, 0, 0, 0, 0,
524 ];
525
526 pub const DEFAULT_NONCE: [u8; 24] = [
527 57, 18, 79, 116, 63, 134, 93, 39, 208, 161, 156, 229, 222, 247, 111, 79, 210, 126, 127, 55,
528 224, 150, 139, 80,
529 ];
530
531 pub fn into_owned(self) -> DelegateRequest<'static> {
532 match self {
533 DelegateRequest::ApplicationMessages {
534 key,
535 inbound,
536 params,
537 } => DelegateRequest::ApplicationMessages {
538 key,
539 params: params.into_owned(),
540 inbound: inbound.into_iter().map(|e| e.into_owned()).collect(),
541 },
542 DelegateRequest::GetSecretRequest {
543 key,
544 get_request,
545 params,
546 } => DelegateRequest::GetSecretRequest {
547 key,
548 get_request,
549 params: params.into_owned(),
550 },
551 DelegateRequest::RegisterDelegate {
552 delegate,
553 cipher,
554 nonce,
555 } => DelegateRequest::RegisterDelegate {
556 delegate,
557 cipher,
558 nonce,
559 },
560 DelegateRequest::UnregisterDelegate(key) => DelegateRequest::UnregisterDelegate(key),
561 }
562 }
563
564 pub fn key(&self) -> &DelegateKey {
565 match self {
566 DelegateRequest::ApplicationMessages { key, .. } => key,
567 DelegateRequest::GetSecretRequest { key, .. } => key,
568 DelegateRequest::RegisterDelegate { delegate, .. } => delegate.key(),
569 DelegateRequest::UnregisterDelegate(key) => key,
570 }
571 }
572}
573
574impl Display for ClientRequest<'_> {
575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576 match self {
577 ClientRequest::ContractOp(op) => match op {
578 ContractRequest::Put {
579 contract, state, ..
580 } => {
581 write!(
582 f,
583 "ContractRequest::Put for contract `{contract}` with state {state}"
584 )
585 }
586 ContractRequest::Update { key, .. } => write!(f, "update request for {key}"),
587 ContractRequest::Get {
588 key,
589 return_contract_code: contract,
590 ..
591 } => {
592 write!(
593 f,
594 "ContractRequest::Get for key `{key}` (fetch full contract: {contract})"
595 )
596 }
597 ContractRequest::Subscribe { key, .. } => {
598 write!(f, "ContractRequest::Subscribe for `{key}`")
599 }
600 },
601 ClientRequest::DelegateOp(op) => {
602 match op {
603 DelegateRequest::ApplicationMessages { key, inbound, .. } => {
604 write!(
605 f,
606 "DelegateRequest::ApplicationMessages for `{key}` with {} messages",
607 inbound.len()
608 )
609 }
610 DelegateRequest::GetSecretRequest {
611 get_request: GetSecretRequest { key: secret_id, .. },
612 key,
613 ..
614 } => {
615 write!(f, "DelegateRequest::GetSecretRequest secret_id `{secret_id}` for key `{key}`")
616 }
617 DelegateRequest::RegisterDelegate { delegate, .. } => {
618 write!(
619 f,
620 "DelegateRequest::RegisterDelegate for delegate.key()=`{}`",
621 delegate.key()
622 )
623 }
624 DelegateRequest::UnregisterDelegate(key) => {
625 write!(f, "DelegateRequest::UnregisterDelegate for key `{key}`")
626 }
627 }
628 }
629 ClientRequest::Disconnect { .. } => write!(f, "client disconnected"),
630 ClientRequest::Authenticate { .. } => write!(f, "authenticate"),
631 ClientRequest::NodeQueries(query) => write!(f, "node queries: {:?}", query),
632 ClientRequest::Close => write!(f, "close"),
633 }
634 }
635}
636
637impl<'a> TryFromFbs<&FbsDelegateRequest<'a>> for DelegateRequest<'a> {
639 fn try_decode_fbs(request: &FbsDelegateRequest<'a>) -> Result<Self, WsApiError> {
640 let req = {
641 match request.delegate_request_type() {
642 DelegateRequestType::ApplicationMessages => {
643 let app_msg = request.delegate_request_as_application_messages().unwrap();
644 let key = DelegateKey::try_decode_fbs(&app_msg.key())?;
645 let params = Parameters::from(app_msg.params().bytes());
646 let inbound = app_msg
647 .inbound()
648 .iter()
649 .map(|msg| InboundDelegateMsg::try_decode_fbs(&msg))
650 .collect::<Result<Vec<_>, _>>()?;
651 DelegateRequest::ApplicationMessages {
652 key,
653 params,
654 inbound,
655 }
656 }
657 DelegateRequestType::GetSecretRequestType => {
658 let get_secret = request
659 .delegate_request_as_get_secret_request_type()
660 .unwrap();
661 let key = DelegateKey::try_decode_fbs(&get_secret.key())?;
662 let params = Parameters::from(get_secret.params().bytes().to_vec());
663 let get_request = GetSecretRequest {
664 key: SecretsId::try_decode_fbs(&get_secret.get_request().key())?,
665 context: DelegateContext::new(
666 get_secret.get_request().delegate_context().bytes().to_vec(),
667 ),
668 processed: get_secret.get_request().processed(),
669 };
670 DelegateRequest::GetSecretRequest {
671 key,
672 params,
673 get_request,
674 }
675 }
676 DelegateRequestType::RegisterDelegate => {
677 let register = request.delegate_request_as_register_delegate().unwrap();
678 let delegate = DelegateContainer::try_decode_fbs(®ister.delegate())?;
679 let cipher =
680 <[u8; 32]>::try_from(register.cipher().bytes().to_vec().as_slice())
681 .unwrap();
682 let nonce =
683 <[u8; 24]>::try_from(register.nonce().bytes().to_vec().as_slice()).unwrap();
684 DelegateRequest::RegisterDelegate {
685 delegate,
686 cipher,
687 nonce,
688 }
689 }
690 DelegateRequestType::UnregisterDelegate => {
691 let unregister = request.delegate_request_as_unregister_delegate().unwrap();
692 let key = DelegateKey::try_decode_fbs(&unregister.key())?;
693 DelegateRequest::UnregisterDelegate(key)
694 }
695 _ => unreachable!(),
696 }
697 };
698
699 Ok(req)
700 }
701}
702
703#[derive(Serialize, Deserialize, Debug)]
705#[non_exhaustive]
706pub enum HostResponse<T = WrappedState> {
707 ContractResponse(#[serde(bound(deserialize = "T: DeserializeOwned"))] ContractResponse<T>),
708 DelegateResponse {
709 key: DelegateKey,
710 values: Vec<OutboundDelegateMsg>,
711 },
712 QueryResponse(QueryResponse),
713 Ok,
715}
716
717type Peer = String;
718
719#[derive(Serialize, Deserialize, Debug)]
720pub enum QueryResponse {
721 ConnectedPeers { peers: Vec<(Peer, SocketAddr)> },
722}
723
724impl HostResponse {
725 pub fn unwrap_put(self) -> ContractKey {
726 if let Self::ContractResponse(ContractResponse::PutResponse { key }) = self {
727 key
728 } else {
729 panic!("called `HostResponse::unwrap_put()` on other than `PutResponse` value")
730 }
731 }
732
733 pub fn unwrap_get(self) -> (WrappedState, Option<ContractContainer>) {
734 if let Self::ContractResponse(ContractResponse::GetResponse {
735 contract, state, ..
736 }) = self
737 {
738 (state, contract)
739 } else {
740 panic!("called `HostResponse::unwrap_put()` on other than `PutResponse` value")
741 }
742 }
743
744 pub fn into_fbs_bytes(self) -> Result<Vec<u8>, Box<ClientError>> {
745 let mut builder = flatbuffers::FlatBufferBuilder::new();
746 match self {
747 HostResponse::ContractResponse(res) => match res {
748 ContractResponse::PutResponse { key } => {
749 let instance_data = builder.create_vector(key.as_bytes());
750 let instance_offset = ContractInstanceId::create(
751 &mut builder,
752 &ContractInstanceIdArgs {
753 data: Some(instance_data),
754 },
755 );
756
757 let code = key
758 .code_hash()
759 .map(|code| builder.create_vector(code.0.as_ref()));
760 let key_offset = FbsContractKey::create(
761 &mut builder,
762 &ContractKeyArgs {
763 instance: Some(instance_offset),
764 code,
765 },
766 );
767
768 let put_offset = FbsPutResponse::create(
769 &mut builder,
770 &PutResponseArgs {
771 key: Some(key_offset),
772 },
773 );
774
775 let contract_response_offset = FbsContractResponse::create(
776 &mut builder,
777 &ContractResponseArgs {
778 contract_response: Some(put_offset.as_union_value()),
779 contract_response_type: ContractResponseType::PutResponse,
780 },
781 );
782
783 let response_offset = FbsHostResponse::create(
784 &mut builder,
785 &HostResponseArgs {
786 response: Some(contract_response_offset.as_union_value()),
787 response_type: HostResponseType::ContractResponse,
788 },
789 );
790
791 finish_host_response_buffer(&mut builder, response_offset);
792 Ok(builder.finished_data().to_vec())
793 }
794 ContractResponse::UpdateResponse { key, summary } => {
795 let instance_data = builder.create_vector(key.as_bytes());
796 let instance_offset = ContractInstanceId::create(
797 &mut builder,
798 &ContractInstanceIdArgs {
799 data: Some(instance_data),
800 },
801 );
802
803 let code = key
804 .code_hash()
805 .map(|code| builder.create_vector(code.0.as_ref()));
806
807 let key_offset = FbsContractKey::create(
808 &mut builder,
809 &ContractKeyArgs {
810 instance: Some(instance_offset),
811 code,
812 },
813 );
814
815 let summary_data = builder.create_vector(&summary.into_bytes());
816
817 let update_response_offset = FbsUpdateResponse::create(
818 &mut builder,
819 &UpdateResponseArgs {
820 key: Some(key_offset),
821 summary: Some(summary_data),
822 },
823 );
824
825 let contract_response_offset = FbsContractResponse::create(
826 &mut builder,
827 &ContractResponseArgs {
828 contract_response: Some(update_response_offset.as_union_value()),
829 contract_response_type: ContractResponseType::UpdateResponse,
830 },
831 );
832
833 let response_offset = FbsHostResponse::create(
834 &mut builder,
835 &HostResponseArgs {
836 response: Some(contract_response_offset.as_union_value()),
837 response_type: HostResponseType::ContractResponse,
838 },
839 );
840
841 finish_host_response_buffer(&mut builder, response_offset);
842 Ok(builder.finished_data().to_vec())
843 }
844 ContractResponse::GetResponse {
845 key,
846 contract: contract_container,
847 state,
848 } => {
849 let instance_data = builder.create_vector(key.as_bytes());
850 let instance_offset = ContractInstanceId::create(
851 &mut builder,
852 &ContractInstanceIdArgs {
853 data: Some(instance_data),
854 },
855 );
856
857 let code = key.code_hash().map(|code| builder.create_vector(&code.0));
858 let key_offset = FbsContractKey::create(
859 &mut builder,
860 &ContractKeyArgs {
861 instance: Some(instance_offset),
862 code,
863 },
864 );
865
866 let container_offset = if let Some(contract) = contract_container {
867 let data = builder.create_vector(contract.key().as_bytes());
868
869 let instance_offset = ContractInstanceId::create(
870 &mut builder,
871 &ContractInstanceIdArgs { data: Some(data) },
872 );
873
874 let code = contract
875 .key()
876 .code_hash()
877 .map(|code| builder.create_vector(&code.0));
878 let contract_key_offset = FbsContractKey::create(
879 &mut builder,
880 &ContractKeyArgs {
881 instance: Some(instance_offset),
882 code,
883 },
884 );
885
886 let contract_data =
887 builder.create_vector(contract.clone().unwrap_v1().data.data());
888 let contract_code_hash =
889 builder.create_vector(&contract.clone().unwrap_v1().data.hash().0);
890
891 let contract_code_offset = ContractCode::create(
892 &mut builder,
893 &ContractCodeArgs {
894 data: Some(contract_data),
895 code_hash: Some(contract_code_hash),
896 },
897 );
898
899 let contract_params =
900 builder.create_vector(&contract.clone().params().into_bytes());
901
902 let contract_offset = match contract {
903 Wasm(V1(..)) => WasmContractV1::create(
904 &mut builder,
905 &WasmContractV1Args {
906 key: Some(contract_key_offset),
907 data: Some(contract_code_offset),
908 parameters: Some(contract_params),
909 },
910 ),
911 };
912
913 Some(FbsContractContainer::create(
914 &mut builder,
915 &ContractContainerArgs {
916 contract_type: ContractType::WasmContractV1,
917 contract: Some(contract_offset.as_union_value()),
918 },
919 ))
920 } else {
921 None
922 };
923
924 let state_data = builder.create_vector(&state);
925
926 let get_offset = FbsGetResponse::create(
927 &mut builder,
928 &GetResponseArgs {
929 key: Some(key_offset),
930 contract: container_offset,
931 state: Some(state_data),
932 },
933 );
934
935 let contract_response_offset = FbsContractResponse::create(
936 &mut builder,
937 &ContractResponseArgs {
938 contract_response_type: ContractResponseType::GetResponse,
939 contract_response: Some(get_offset.as_union_value()),
940 },
941 );
942
943 let response_offset = FbsHostResponse::create(
944 &mut builder,
945 &HostResponseArgs {
946 response: Some(contract_response_offset.as_union_value()),
947 response_type: HostResponseType::ContractResponse,
948 },
949 );
950
951 finish_host_response_buffer(&mut builder, response_offset);
952 Ok(builder.finished_data().to_vec())
953 }
954 ContractResponse::UpdateNotification { key, update } => {
955 let instance_data = builder.create_vector(key.as_bytes());
956 let instance_offset = ContractInstanceId::create(
957 &mut builder,
958 &ContractInstanceIdArgs {
959 data: Some(instance_data),
960 },
961 );
962
963 let code = key
964 .code_hash()
965 .map(|code| builder.create_vector(code.0.as_ref()));
966 let key_offset = FbsContractKey::create(
967 &mut builder,
968 &ContractKeyArgs {
969 instance: Some(instance_offset),
970 code,
971 },
972 );
973
974 let update_data = match update {
975 State(state) => {
976 let state_data = builder.create_vector(&state.into_bytes());
977 let state_update_offset = StateUpdate::create(
978 &mut builder,
979 &StateUpdateArgs {
980 state: Some(state_data),
981 },
982 );
983 FbsUpdateData::create(
984 &mut builder,
985 &UpdateDataArgs {
986 update_data_type: UpdateDataType::StateUpdate,
987 update_data: Some(state_update_offset.as_union_value()),
988 },
989 )
990 }
991 Delta(delta) => {
992 let delta_data = builder.create_vector(&delta.into_bytes());
993 let update_offset = DeltaUpdate::create(
994 &mut builder,
995 &DeltaUpdateArgs {
996 delta: Some(delta_data),
997 },
998 );
999 FbsUpdateData::create(
1000 &mut builder,
1001 &UpdateDataArgs {
1002 update_data_type: UpdateDataType::DeltaUpdate,
1003 update_data: Some(update_offset.as_union_value()),
1004 },
1005 )
1006 }
1007 StateAndDelta { state, delta } => {
1008 let state_data = builder.create_vector(&state.into_bytes());
1009 let delta_data = builder.create_vector(&delta.into_bytes());
1010
1011 let update_offset = StateAndDeltaUpdate::create(
1012 &mut builder,
1013 &StateAndDeltaUpdateArgs {
1014 state: Some(state_data),
1015 delta: Some(delta_data),
1016 },
1017 );
1018
1019 FbsUpdateData::create(
1020 &mut builder,
1021 &UpdateDataArgs {
1022 update_data_type: UpdateDataType::StateAndDeltaUpdate,
1023 update_data: Some(update_offset.as_union_value()),
1024 },
1025 )
1026 }
1027 RelatedState { related_to, state } => {
1028 let state_data = builder.create_vector(&state.into_bytes());
1029 let instance_data =
1030 builder.create_vector(related_to.encode().as_bytes());
1031
1032 let instance_offset = ContractInstanceId::create(
1033 &mut builder,
1034 &ContractInstanceIdArgs {
1035 data: Some(instance_data),
1036 },
1037 );
1038
1039 let update_offset = RelatedStateUpdate::create(
1040 &mut builder,
1041 &RelatedStateUpdateArgs {
1042 related_to: Some(instance_offset),
1043 state: Some(state_data),
1044 },
1045 );
1046
1047 FbsUpdateData::create(
1048 &mut builder,
1049 &UpdateDataArgs {
1050 update_data_type: UpdateDataType::RelatedStateUpdate,
1051 update_data: Some(update_offset.as_union_value()),
1052 },
1053 )
1054 }
1055 RelatedDelta { related_to, delta } => {
1056 let instance_data =
1057 builder.create_vector(related_to.encode().as_bytes());
1058 let delta_data = builder.create_vector(&delta.into_bytes());
1059
1060 let instance_offset = ContractInstanceId::create(
1061 &mut builder,
1062 &ContractInstanceIdArgs {
1063 data: Some(instance_data),
1064 },
1065 );
1066
1067 let update_offset = RelatedDeltaUpdate::create(
1068 &mut builder,
1069 &RelatedDeltaUpdateArgs {
1070 related_to: Some(instance_offset),
1071 delta: Some(delta_data),
1072 },
1073 );
1074
1075 FbsUpdateData::create(
1076 &mut builder,
1077 &UpdateDataArgs {
1078 update_data_type: UpdateDataType::RelatedDeltaUpdate,
1079 update_data: Some(update_offset.as_union_value()),
1080 },
1081 )
1082 }
1083 RelatedStateAndDelta {
1084 related_to,
1085 state,
1086 delta,
1087 } => {
1088 let instance_data =
1089 builder.create_vector(related_to.encode().as_bytes());
1090 let state_data = builder.create_vector(&state.into_bytes());
1091 let delta_data = builder.create_vector(&delta.into_bytes());
1092
1093 let instance_offset = ContractInstanceId::create(
1094 &mut builder,
1095 &ContractInstanceIdArgs {
1096 data: Some(instance_data),
1097 },
1098 );
1099
1100 let update_offset = RelatedStateAndDeltaUpdate::create(
1101 &mut builder,
1102 &RelatedStateAndDeltaUpdateArgs {
1103 related_to: Some(instance_offset),
1104 state: Some(state_data),
1105 delta: Some(delta_data),
1106 },
1107 );
1108
1109 FbsUpdateData::create(
1110 &mut builder,
1111 &UpdateDataArgs {
1112 update_data_type: UpdateDataType::RelatedStateAndDeltaUpdate,
1113 update_data: Some(update_offset.as_union_value()),
1114 },
1115 )
1116 }
1117 };
1118
1119 let update_notification_offset = FbsUpdateNotification::create(
1120 &mut builder,
1121 &UpdateNotificationArgs {
1122 key: Some(key_offset),
1123 update: Some(update_data),
1124 },
1125 );
1126
1127 let put_response_offset = FbsContractResponse::create(
1128 &mut builder,
1129 &ContractResponseArgs {
1130 contract_response_type: ContractResponseType::UpdateNotification,
1131 contract_response: Some(update_notification_offset.as_union_value()),
1132 },
1133 );
1134
1135 let host_response_offset = FbsHostResponse::create(
1136 &mut builder,
1137 &HostResponseArgs {
1138 response_type: HostResponseType::ContractResponse,
1139 response: Some(put_response_offset.as_union_value()),
1140 },
1141 );
1142
1143 finish_host_response_buffer(&mut builder, host_response_offset);
1144 Ok(builder.finished_data().to_vec())
1145 }
1146 ContractResponse::SubscribeResponse { .. } => todo!(),
1147 },
1148 HostResponse::DelegateResponse { key, values } => {
1149 let key_data = builder.create_vector(key.bytes());
1150 let code_hash_data = builder.create_vector(&key.code_hash().0);
1151 let key_offset = FbsDelegateKey::create(
1152 &mut builder,
1153 &DelegateKeyArgs {
1154 key: Some(key_data),
1155 code_hash: Some(code_hash_data),
1156 },
1157 );
1158 let mut messages: Vec<WIPOffset<FbsOutboundDelegateMsg>> = Vec::new();
1159 values.iter().for_each(|msg| match msg {
1160 OutboundDelegateMsg::ApplicationMessage(app) => {
1161 let instance_data = builder.create_vector(key.bytes());
1162 let instance_offset = ContractInstanceId::create(
1163 &mut builder,
1164 &ContractInstanceIdArgs {
1165 data: Some(instance_data),
1166 },
1167 );
1168 let payload_data = builder.create_vector(&app.payload);
1169 let delegate_context_data = builder.create_vector(app.context.as_ref());
1170 let app_offset = FbsApplicationMessage::create(
1171 &mut builder,
1172 &ApplicationMessageArgs {
1173 app: Some(instance_offset),
1174 payload: Some(payload_data),
1175 context: Some(delegate_context_data),
1176 processed: app.processed,
1177 },
1178 );
1179 let msg = FbsOutboundDelegateMsg::create(
1180 &mut builder,
1181 &OutboundDelegateMsgArgs {
1182 inbound_type: OutboundDelegateMsgType::common_ApplicationMessage,
1183 inbound: Some(app_offset.as_union_value()),
1184 },
1185 );
1186 messages.push(msg);
1187 }
1188 OutboundDelegateMsg::RequestUserInput(input) => {
1189 let message_data = builder.create_vector(input.message.bytes());
1190 let mut responses: Vec<WIPOffset<FbsClientResponse>> = Vec::new();
1191 input.responses.iter().for_each(|resp| {
1192 let response_data = builder.create_vector(resp.bytes());
1193 let response = FbsClientResponse::create(
1194 &mut builder,
1195 &ClientResponseArgs {
1196 data: Some(response_data),
1197 },
1198 );
1199 responses.push(response)
1200 });
1201 let responses_offset = builder.create_vector(&responses);
1202 let input_offset = FbsRequestUserInput::create(
1203 &mut builder,
1204 &RequestUserInputArgs {
1205 request_id: input.request_id,
1206 message: Some(message_data),
1207 responses: Some(responses_offset),
1208 },
1209 );
1210 let msg = FbsOutboundDelegateMsg::create(
1211 &mut builder,
1212 &OutboundDelegateMsgArgs {
1213 inbound_type: OutboundDelegateMsgType::RequestUserInput,
1214 inbound: Some(input_offset.as_union_value()),
1215 },
1216 );
1217 messages.push(msg);
1218 }
1219 OutboundDelegateMsg::ContextUpdated(context) => {
1220 let context_data = builder.create_vector(context.as_ref());
1221 let context_offset = FbsContextUpdated::create(
1222 &mut builder,
1223 &ContextUpdatedArgs {
1224 context: Some(context_data),
1225 },
1226 );
1227 let msg = FbsOutboundDelegateMsg::create(
1228 &mut builder,
1229 &OutboundDelegateMsgArgs {
1230 inbound_type: OutboundDelegateMsgType::ContextUpdated,
1231 inbound: Some(context_offset.as_union_value()),
1232 },
1233 );
1234 messages.push(msg);
1235 }
1236 OutboundDelegateMsg::GetSecretRequest(request) => {
1237 let secret_key_data = builder.create_vector(request.key.key());
1238 let secret_hash_data = builder.create_vector(request.key.hash());
1239 let secret_id_offset = FbsSecretsId::create(
1240 &mut builder,
1241 &SecretsIdArgs {
1242 key: Some(secret_key_data),
1243 hash: Some(secret_hash_data),
1244 },
1245 );
1246
1247 let delegate_context_data = builder.create_vector(request.context.as_ref());
1248 let request_offset = FbsGetSecretRequest::create(
1249 &mut builder,
1250 &GetSecretRequestArgs {
1251 key: Some(secret_id_offset),
1252 delegate_context: Some(delegate_context_data),
1253 processed: request.processed,
1254 },
1255 );
1256 let msg = FbsOutboundDelegateMsg::create(
1257 &mut builder,
1258 &OutboundDelegateMsgArgs {
1259 inbound_type: OutboundDelegateMsgType::common_GetSecretRequest,
1260 inbound: Some(request_offset.as_union_value()),
1261 },
1262 );
1263 messages.push(msg);
1264 }
1265 OutboundDelegateMsg::SetSecretRequest(request) => {
1266 let secret_key_data = builder.create_vector(request.key.key());
1267 let secret_hash_data = builder.create_vector(request.key.hash());
1268 let secret_id_offset = FbsSecretsId::create(
1269 &mut builder,
1270 &SecretsIdArgs {
1271 key: Some(secret_key_data),
1272 hash: Some(secret_hash_data),
1273 },
1274 );
1275
1276 let value_data = request
1277 .value
1278 .clone()
1279 .map(|value| builder.create_vector(value.as_slice()));
1280 let request_offset = FbsSetSecretRequest::create(
1281 &mut builder,
1282 &SetSecretRequestArgs {
1283 key: Some(secret_id_offset),
1284 value: value_data,
1285 },
1286 );
1287 let msg = FbsOutboundDelegateMsg::create(
1288 &mut builder,
1289 &OutboundDelegateMsgArgs {
1290 inbound_type: OutboundDelegateMsgType::SetSecretRequest,
1291 inbound: Some(request_offset.as_union_value()),
1292 },
1293 );
1294 messages.push(msg);
1295 }
1296 OutboundDelegateMsg::GetSecretResponse(response) => {
1297 let secret_key_data = builder.create_vector(response.key.key());
1298 let secret_hash_data = builder.create_vector(response.key.hash());
1299 let secret_id_offset = FbsSecretsId::create(
1300 &mut builder,
1301 &SecretsIdArgs {
1302 key: Some(secret_key_data),
1303 hash: Some(secret_hash_data),
1304 },
1305 );
1306
1307 let value_data = response
1308 .value
1309 .clone()
1310 .map(|value| builder.create_vector(value.as_slice()));
1311
1312 let delegate_context_data =
1313 builder.create_vector(response.context.as_ref());
1314 let response_offset = FbsGetSecretResponse::create(
1315 &mut builder,
1316 &GetSecretResponseArgs {
1317 key: Some(secret_id_offset),
1318 value: value_data,
1319 delegate_context: Some(delegate_context_data),
1320 },
1321 );
1322 let msg = FbsOutboundDelegateMsg::create(
1323 &mut builder,
1324 &OutboundDelegateMsgArgs {
1325 inbound_type: OutboundDelegateMsgType::common_GetSecretResponse,
1326 inbound: Some(response_offset.as_union_value()),
1327 },
1328 );
1329 messages.push(msg);
1330 }
1331 });
1332 let messages_offset = builder.create_vector(&messages);
1333 let delegate_response_offset = FbsDelegateResponse::create(
1334 &mut builder,
1335 &DelegateResponseArgs {
1336 key: Some(key_offset),
1337 values: Some(messages_offset),
1338 },
1339 );
1340 let host_response_offset = FbsHostResponse::create(
1341 &mut builder,
1342 &HostResponseArgs {
1343 response_type: HostResponseType::DelegateResponse,
1344 response: Some(delegate_response_offset.as_union_value()),
1345 },
1346 );
1347 finish_host_response_buffer(&mut builder, host_response_offset);
1348 Ok(builder.finished_data().to_vec())
1349 }
1350 HostResponse::Ok => {
1351 let ok_offset = FbsOk::create(&mut builder, &OkArgs { msg: None });
1352 let host_response_offset = FbsHostResponse::create(
1353 &mut builder,
1354 &HostResponseArgs {
1355 response_type: HostResponseType::Ok,
1356 response: Some(ok_offset.as_union_value()),
1357 },
1358 );
1359 finish_host_response_buffer(&mut builder, host_response_offset);
1360 Ok(builder.finished_data().to_vec())
1361 }
1362 HostResponse::QueryResponse(_) => unimplemented!(),
1363 }
1364 }
1365}
1366
1367impl Display for HostResponse {
1368 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1369 match self {
1370 HostResponse::ContractResponse(res) => match res {
1371 ContractResponse::PutResponse { key } => {
1372 f.write_fmt(format_args!("put response for `{key}`"))
1373 }
1374 ContractResponse::UpdateResponse { key, .. } => {
1375 f.write_fmt(format_args!("update response for `{key}`"))
1376 }
1377 ContractResponse::GetResponse { key, .. } => {
1378 f.write_fmt(format_args!("get response for `{key}`"))
1379 }
1380 ContractResponse::UpdateNotification { key, .. } => {
1381 f.write_fmt(format_args!("update notification for `{key}`"))
1382 }
1383 ContractResponse::SubscribeResponse { key, .. } => {
1384 f.write_fmt(format_args!("subscribe response for `{key}`"))
1385 }
1386 },
1387 HostResponse::DelegateResponse { .. } => write!(f, "delegate responses"),
1388 HostResponse::Ok => write!(f, "ok response"),
1389 HostResponse::QueryResponse(_) => write!(f, "query response"),
1390 }
1391 }
1392}
1393
1394#[derive(Clone, Serialize, Deserialize, Debug)]
1395#[non_exhaustive]
1396pub enum ContractResponse<T = WrappedState> {
1397 GetResponse {
1398 key: ContractKey,
1399 contract: Option<ContractContainer>,
1400 #[serde(bound(deserialize = "T: DeserializeOwned"))]
1401 state: T,
1402 },
1403 PutResponse {
1404 key: ContractKey,
1405 },
1406 UpdateNotification {
1408 key: ContractKey,
1409 #[serde(deserialize_with = "UpdateData::deser_update_data")]
1410 update: UpdateData<'static>,
1411 },
1412 UpdateResponse {
1414 key: ContractKey,
1415 #[serde(deserialize_with = "StateSummary::deser_state_summary")]
1416 summary: StateSummary<'static>,
1417 },
1418 SubscribeResponse {
1419 key: ContractKey,
1420 subscribed: bool,
1421 },
1422}
1423
1424impl<T> From<ContractResponse<T>> for HostResponse<T> {
1425 fn from(value: ContractResponse<T>) -> HostResponse<T> {
1426 HostResponse::ContractResponse(value)
1427 }
1428}
1429
1430#[cfg(test)]
1431mod client_request_test {
1432 use crate::client_api::{ContractRequest, TryFromFbs};
1433 use crate::contract_interface::UpdateData;
1434 use crate::generated::client_request::root_as_client_request;
1435
1436 const EXPECTED_ENCODED_CONTRACT_ID: &str = "6kVs66bKaQAC6ohr8b43SvJ95r36tc2hnG7HezmaJHF9";
1437
1438 #[test]
1439 fn test_build_contract_put_op_from_fbs() -> Result<(), Box<dyn std::error::Error>> {
1440 let put_req_op = vec![
1441 4, 0, 0, 0, 244, 255, 255, 255, 16, 0, 0, 0, 0, 0, 0, 1, 8, 0, 12, 0, 11, 0, 4, 0, 8,
1442 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 198, 255, 255, 255, 12, 0, 0, 0, 20, 0, 0, 0, 36, 0,
1443 0, 0, 170, 255, 255, 255, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
1444 8, 0, 10, 0, 9, 0, 4, 0, 8, 0, 0, 0, 16, 0, 0, 0, 0, 1, 10, 0, 16, 0, 12, 0, 8, 0, 4,
1445 0, 10, 0, 0, 0, 12, 0, 0, 0, 76, 0, 0, 0, 92, 0, 0, 0, 176, 255, 255, 255, 8, 0, 0, 0,
1446 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0,
1447 85, 111, 11, 171, 40, 85, 240, 177, 207, 81, 106, 157, 173, 90, 234, 2, 250, 253, 75,
1448 210, 62, 7, 6, 34, 75, 26, 229, 230, 107, 167, 17, 108, 8, 0, 0, 0, 1, 2, 3, 4, 5, 6,
1449 7, 8, 8, 0, 12, 0, 8, 0, 4, 0, 8, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 8, 0, 0, 0, 1, 2,
1450 3, 4, 5, 6, 7, 8, 8, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
1451 ];
1452 let request = if let Ok(client_request) = root_as_client_request(&put_req_op) {
1453 let contract_request = client_request.client_request_as_contract_request().unwrap();
1454 ContractRequest::try_decode_fbs(&contract_request)?
1455 } else {
1456 panic!("failed to decode client request")
1457 };
1458
1459 match request {
1460 ContractRequest::Put {
1461 contract,
1462 state,
1463 related_contracts: _,
1464 subscribe,
1465 } => {
1466 assert_eq!(
1467 contract.to_string(),
1468 "WasmContainer([api=0.0.1](D8fdVLbRyMLw5mZtPRpWMFcrXGN2z8Nq8UGcLGPFBg2W))"
1469 );
1470 assert_eq!(contract.unwrap_v1().data.data(), &[1, 2, 3, 4, 5, 6, 7, 8]);
1471 assert_eq!(state.to_vec(), &[1, 2, 3, 4, 5, 6, 7, 8]);
1472 assert!(!subscribe);
1473 }
1474 _ => panic!("wrong contract request type"),
1475 }
1476
1477 Ok(())
1478 }
1479
1480 #[test]
1481 fn test_build_contract_get_op_from_fbs() -> Result<(), Box<dyn std::error::Error>> {
1482 let get_req_op = vec![
1483 4, 0, 0, 0, 244, 255, 255, 255, 16, 0, 0, 0, 0, 0, 0, 1, 8, 0, 12, 0, 11, 0, 4, 0, 8,
1484 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 3, 222, 255, 255, 255, 12, 0, 0, 0, 8, 0, 12, 0, 8, 0, 4,
1485 0, 8, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0,
1486 4, 0, 0, 0, 32, 0, 0, 0, 85, 111, 11, 171, 40, 85, 240, 177, 207, 81, 106, 157, 173,
1487 90, 234, 2, 250, 253, 75, 210, 62, 7, 6, 34, 75, 26, 229, 230, 107, 167, 17, 108,
1488 ];
1489 let request = if let Ok(client_request) = root_as_client_request(&get_req_op) {
1490 let contract_request = client_request.client_request_as_contract_request().unwrap();
1491 ContractRequest::try_decode_fbs(&contract_request)?
1492 } else {
1493 panic!("failed to decode client request")
1494 };
1495
1496 match request {
1497 ContractRequest::Get {
1498 key,
1499 return_contract_code: fetch_contract,
1500 subscribe,
1501 } => {
1502 assert_eq!(key.encoded_contract_id(), EXPECTED_ENCODED_CONTRACT_ID);
1503 assert!(!fetch_contract);
1504 assert!(!subscribe);
1505 }
1506 _ => panic!("wrong contract request type"),
1507 }
1508
1509 Ok(())
1510 }
1511
1512 #[test]
1513 fn test_build_contract_update_op_from_fbs() -> Result<(), Box<dyn std::error::Error>> {
1514 let update_op = vec![
1515 4, 0, 0, 0, 220, 255, 255, 255, 8, 0, 0, 0, 0, 0, 0, 1, 232, 255, 255, 255, 8, 0, 0, 0,
1516 0, 0, 0, 2, 204, 255, 255, 255, 16, 0, 0, 0, 52, 0, 0, 0, 8, 0, 12, 0, 11, 0, 4, 0, 8,
1517 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 2, 210, 255, 255, 255, 4, 0, 0, 0, 8, 0, 0, 0, 1, 2, 3,
1518 4, 5, 6, 7, 8, 8, 0, 12, 0, 8, 0, 4, 0, 8, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0,
1519 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0, 85, 111, 11, 171, 40,
1520 85, 240, 177, 207, 81, 106, 157, 173, 90, 234, 2, 250, 253, 75, 210, 62, 7, 6, 34, 75,
1521 26, 229, 230, 107, 167, 17, 108,
1522 ];
1523 let request = if let Ok(client_request) = root_as_client_request(&update_op) {
1524 let contract_request = client_request.client_request_as_contract_request().unwrap();
1525 ContractRequest::try_decode_fbs(&contract_request)?
1526 } else {
1527 panic!("failed to decode client request")
1528 };
1529
1530 match request {
1531 ContractRequest::Update { key, data } => {
1532 assert_eq!(
1533 key.encoded_contract_id(),
1534 "6kVs66bKaQAC6ohr8b43SvJ95r36tc2hnG7HezmaJHF9"
1535 );
1536 match data {
1537 UpdateData::Delta(delta) => {
1538 assert_eq!(delta.to_vec(), &[1, 2, 3, 4, 5, 6, 7, 8])
1539 }
1540 _ => panic!("wrong update data type"),
1541 }
1542 }
1543 _ => panic!("wrong contract request type"),
1544 }
1545
1546 Ok(())
1547 }
1548}