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