1use crate::error::{anyhow, bail, AnyError, AnyResult};
4use cosmwasm_std::{
5 from_json, Binary, Checksum, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env,
6 IbcSourceCallbackMsg, MessageInfo, QuerierWrapper, Reply, Response, SubMsg,
7};
8use cosmwasm_std::{
9 IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
10 IbcChannelOpenResponse, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
11 IbcReceiveResponse,
12};
13use ibc::{IbcClosure, IbcFn};
14use serde::de::DeserializeOwned;
15use std::fmt::{Debug, Display};
16use std::ops::Deref;
17
18#[rustfmt::skip]
20pub trait Contract<C, Q = Empty>
21where
22 C: CustomMsg,
23 Q: CustomQuery,
24{
25 fn execute(&self, deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: Vec<u8>) -> AnyResult<Response<C>>;
27
28 fn instantiate(&self, deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: Vec<u8>) -> AnyResult<Response<C>>;
30
31 fn query(&self, deps: Deps<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Binary>;
33
34 fn sudo(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>>;
36
37 fn reply(&self, deps: DepsMut<Q>, env: Env, msg: Reply) -> AnyResult<Response<C>>;
39
40 fn migrate(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>>;
42
43 fn checksum(&self) -> Option<Checksum> {
45 None
46 }
47
48 #[allow(unused)]
50 fn ibc_channel_open(
51 &self,
52 deps: DepsMut<Q>,
53 env: Env,
54 msg: IbcChannelOpenMsg,
55 ) -> AnyResult<IbcChannelOpenResponse> {
56 bail!("No Ibc capabilities on this contract")
57 }
58
59 #[allow(unused)]
61 fn ibc_channel_connect(
62 &self,
63 deps: DepsMut<Q>,
64 env: Env,
65 msg: IbcChannelConnectMsg,
66 ) -> AnyResult<IbcBasicResponse<C>> {
67 bail!("No Ibc capabilities on this contract")
68 }
69
70 #[allow(unused)]
72 fn ibc_channel_close(
73 &self,
74 deps: DepsMut<Q>,
75 env: Env,
76 msg: IbcChannelCloseMsg,
77 ) -> AnyResult<IbcBasicResponse<C>> {
78 bail!("No Ibc capabilities on this contract")
79 }
80
81 #[allow(unused)]
83 fn ibc_packet_receive(
84 &self,
85 deps: DepsMut<Q>,
86 env: Env,
87 msg: IbcPacketReceiveMsg,
88 ) -> AnyResult<IbcReceiveResponse<C>> {
89 bail!("No Ibc capabilities on this contract")
90 }
91
92 #[allow(unused)]
94 fn ibc_packet_acknowledge(
95 &self,
96 deps: DepsMut<Q>,
97 env: Env,
98 msg: IbcPacketAckMsg,
99 ) -> AnyResult<IbcBasicResponse<C>> {
100 bail!("No Ibc capabilities on this contract")
101 }
102
103 #[allow(unused)]
105 fn ibc_packet_timeout(
106 &self,
107 deps: DepsMut<Q>,
108 env: Env,
109 msg: IbcPacketTimeoutMsg,
110 ) -> AnyResult<IbcBasicResponse<C>> {
111 bail!("No Ibc capabilities on this contract")
112 }
113
114 #[allow(unused)]
116 fn ibc_source_callback(
117 &self,
118 deps: DepsMut<Q>,
119 env: Env,
120 msg: IbcSourceCallbackMsg,
121 ) -> AnyResult<IbcBasicResponse<C>> {
122 bail!("No Ibc source callback on this contract")
123 }
124
125
126}
127
128#[rustfmt::skip]
129mod closures {
130 use super::*;
131
132 pub type ContractFn<T, C, E, Q> = fn(deps: DepsMut<Q>, env: Env, info: MessageInfo, msg: T) -> Result<Response<C>, E>;
134 pub type PermissionedFn<T, C, E, Q> = fn(deps: DepsMut<Q>, env: Env, msg: T) -> Result<Response<C>, E>;
135 pub type ReplyFn<C, E, Q> = fn(deps: DepsMut<Q>, env: Env, msg: Reply) -> Result<Response<C>, E>;
136 pub type QueryFn<T, E, Q> = fn(deps: Deps<Q>, env: Env, msg: T) -> Result<Binary, E>;
137
138 pub type ContractClosure<T, C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, MessageInfo, T) -> Result<Response<C>, E>>;
140 pub type PermissionedClosure<T, C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, T) -> Result<Response<C>, E>>;
141 pub type ReplyClosure<C, E, Q> = Box<dyn Fn(DepsMut<Q>, Env, Reply) -> Result<Response<C>, E>>;
142 pub type QueryClosure<T, E, Q> = Box<dyn Fn(Deps<Q>, Env, T) -> Result<Binary, E>>;
143
144 pub mod ibc{
145 use super::*;
146 pub type IbcFn<T, R, E, Q> = fn(deps: DepsMut<Q>, env: Env, msg: T) -> Result<R, E>;
147
148 pub type IbcClosure<T, R, E, Q> = Box<dyn Fn(DepsMut<Q>,Env, T) -> Result<R, E>>;
149 }
150}
151
152use closures::*;
153
154pub struct ContractWrapper<
234 T1,
235 T2,
236 T3,
237 E1,
238 E2,
239 E3,
240 C = Empty,
241 Q = Empty,
242 T4 = Empty,
243 E4 = AnyError,
244 E5 = AnyError,
245 T6 = Empty,
246 E6 = AnyError,
247 E7 = AnyError,
248 E8 = AnyError,
249 E9 = AnyError,
250 E10 = AnyError,
251 E11 = AnyError,
252 E12 = AnyError,
253 E13 = AnyError,
254> where
255 T1: DeserializeOwned, T2: DeserializeOwned, T3: DeserializeOwned, T4: DeserializeOwned, T6: DeserializeOwned, E1: Display + Debug + Send + Sync, E2: Display + Debug + Send + Sync, E3: Display + Debug + Send + Sync, E4: Display + Debug + Send + Sync, E5: Display + Debug + Send + Sync, E6: Display + Debug + Send + Sync, E7: Display + Debug + Send + Sync, E8: Display + Debug + Send + Sync, E9: Display + Debug + Send + Sync, E10: Display + Debug + Send + Sync, E11: Display + Debug + Send + Sync, E12: Display + Debug + Send + Sync, E13: Display + Debug + Send + Sync, C: CustomMsg, Q: CustomQuery + DeserializeOwned, {
276 execute_fn: ContractClosure<T1, C, E1, Q>,
277 instantiate_fn: ContractClosure<T2, C, E2, Q>,
278 query_fn: QueryClosure<T3, E3, Q>,
279 sudo_fn: Option<PermissionedClosure<T4, C, E4, Q>>,
280 reply_fn: Option<ReplyClosure<C, E5, Q>>,
281 migrate_fn: Option<PermissionedClosure<T6, C, E6, Q>>,
282 checksum: Option<Checksum>,
283
284 channel_open_fn: Option<IbcClosure<IbcChannelOpenMsg, IbcChannelOpenResponse, E7, Q>>,
285 channel_connect_fn: Option<IbcClosure<IbcChannelConnectMsg, IbcBasicResponse<C>, E8, Q>>,
286 channel_close_fn: Option<IbcClosure<IbcChannelCloseMsg, IbcBasicResponse<C>, E9, Q>>,
287
288 ibc_packet_receive_fn: Option<IbcClosure<IbcPacketReceiveMsg, IbcReceiveResponse<C>, E10, Q>>,
289 ibc_packet_ack_fn: Option<IbcClosure<IbcPacketAckMsg, IbcBasicResponse<C>, E11, Q>>,
290 ibc_packet_timeout_fn: Option<IbcClosure<IbcPacketTimeoutMsg, IbcBasicResponse<C>, E12, Q>>,
291
292 ibc_source_callback: Option<IbcClosure<IbcSourceCallbackMsg, IbcBasicResponse<C>, E13, Q>>,
293}
294
295impl<T1, T2, T3, E1, E2, E3, C, Q> ContractWrapper<T1, T2, T3, E1, E2, E3, C, Q>
296where
297 T1: DeserializeOwned + 'static, T2: DeserializeOwned + 'static, T3: DeserializeOwned + 'static, E1: Display + Debug + Send + Sync + 'static, E2: Display + Debug + Send + Sync + 'static, E3: Display + Debug + Send + Sync + 'static, C: CustomMsg + 'static, Q: CustomQuery + DeserializeOwned + 'static, {
306 pub fn new(
308 execute_fn: ContractFn<T1, C, E1, Q>,
309 instantiate_fn: ContractFn<T2, C, E2, Q>,
310 query_fn: QueryFn<T3, E3, Q>,
311 ) -> Self {
312 Self {
313 execute_fn: Box::new(execute_fn),
314 instantiate_fn: Box::new(instantiate_fn),
315 query_fn: Box::new(query_fn),
316 sudo_fn: None,
317 reply_fn: None,
318 migrate_fn: None,
319 checksum: None,
320
321 channel_open_fn: None,
322 channel_connect_fn: None,
323 channel_close_fn: None,
324
325 ibc_packet_receive_fn: None,
326 ibc_packet_ack_fn: None,
327 ibc_packet_timeout_fn: None,
328
329 ibc_source_callback: None,
330 }
331 }
332
333 pub fn new_with_empty(
336 execute_fn: ContractFn<T1, Empty, E1, Empty>,
337 instantiate_fn: ContractFn<T2, Empty, E2, Empty>,
338 query_fn: QueryFn<T3, E3, Empty>,
339 ) -> Self {
340 Self {
341 execute_fn: customize_contract_fn(execute_fn),
342 instantiate_fn: customize_contract_fn(instantiate_fn),
343 query_fn: customize_query_fn(query_fn),
344 sudo_fn: None,
345 reply_fn: None,
346 migrate_fn: None,
347 checksum: None,
348
349 channel_open_fn: None,
350 channel_connect_fn: None,
351 channel_close_fn: None,
352
353 ibc_packet_receive_fn: None,
354 ibc_packet_ack_fn: None,
355 ibc_packet_timeout_fn: None,
356
357 ibc_source_callback: None,
358 }
359 }
360}
361
362#[allow(clippy::type_complexity)]
363impl<T1, T2, T3, E1, E2, E3, C, Q, T4, E4, E5, T6, E6, E7, E8, E9, E10, E11, E12, E13>
364 ContractWrapper<
365 T1,
366 T2,
367 T3,
368 E1,
369 E2,
370 E3,
371 C,
372 Q,
373 T4,
374 E4,
375 E5,
376 T6,
377 E6,
378 E7,
379 E8,
380 E9,
381 E10,
382 E11,
383 E12,
384 E13,
385 >
386where
387 T1: DeserializeOwned, T2: DeserializeOwned, T3: DeserializeOwned, T4: DeserializeOwned, T6: DeserializeOwned, E1: Display + Debug + Send + Sync, E2: Display + Debug + Send + Sync, E3: Display + Debug + Send + Sync, E4: Display + Debug + Send + Sync, E5: Display + Debug + Send + Sync, E6: Display + Debug + Send + Sync, E7: Display + Debug + Send + Sync, E8: Display + Debug + Send + Sync, E9: Display + Debug + Send + Sync, E10: Display + Debug + Send + Sync, E11: Display + Debug + Send + Sync, E12: Display + Debug + Send + Sync, E13: Display + Debug + Send + Sync, C: CustomMsg + 'static, Q: CustomQuery + DeserializeOwned + 'static, {
408 pub fn with_sudo<T4A, E4A>(
410 self,
411 sudo_fn: PermissionedFn<T4A, C, E4A, Q>,
412 ) -> ContractWrapper<
413 T1,
414 T2,
415 T3,
416 E1,
417 E2,
418 E3,
419 C,
420 Q,
421 T4A,
422 E4A,
423 E5,
424 T6,
425 E6,
426 E7,
427 E8,
428 E9,
429 E10,
430 E11,
431 E12,
432 E13,
433 >
434 where
435 T4A: DeserializeOwned + 'static,
436 E4A: Display + Debug + Send + Sync + 'static,
437 {
438 ContractWrapper {
439 execute_fn: self.execute_fn,
440 instantiate_fn: self.instantiate_fn,
441 query_fn: self.query_fn,
442 sudo_fn: Some(Box::new(sudo_fn)),
443 reply_fn: self.reply_fn,
444 migrate_fn: self.migrate_fn,
445 checksum: None,
446
447 channel_open_fn: self.channel_open_fn,
448 channel_connect_fn: self.channel_connect_fn,
449 channel_close_fn: self.channel_close_fn,
450
451 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
452 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
453 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
454
455 ibc_source_callback: self.ibc_source_callback,
456 }
457 }
458
459 pub fn with_sudo_empty<T4A, E4A>(
461 self,
462 sudo_fn: PermissionedFn<T4A, Empty, E4A, Empty>,
463 ) -> ContractWrapper<
464 T1,
465 T2,
466 T3,
467 E1,
468 E2,
469 E3,
470 C,
471 Q,
472 T4A,
473 E4A,
474 E5,
475 T6,
476 E6,
477 E7,
478 E8,
479 E9,
480 E10,
481 E11,
482 E12,
483 E13,
484 >
485 where
486 T4A: DeserializeOwned + 'static,
487 E4A: Display + Debug + Send + Sync + 'static,
488 {
489 ContractWrapper {
490 execute_fn: self.execute_fn,
491 instantiate_fn: self.instantiate_fn,
492 query_fn: self.query_fn,
493 sudo_fn: Some(customize_permissioned_fn(sudo_fn)),
494 reply_fn: self.reply_fn,
495 migrate_fn: self.migrate_fn,
496 checksum: None,
497
498 channel_open_fn: self.channel_open_fn,
499 channel_connect_fn: self.channel_connect_fn,
500 channel_close_fn: self.channel_close_fn,
501
502 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
503 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
504 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
505
506 ibc_source_callback: self.ibc_source_callback,
507 }
508 }
509
510 pub fn with_reply<E5A>(
512 self,
513 reply_fn: ReplyFn<C, E5A, Q>,
514 ) -> ContractWrapper<
515 T1,
516 T2,
517 T3,
518 E1,
519 E2,
520 E3,
521 C,
522 Q,
523 T4,
524 E4,
525 E5A,
526 T6,
527 E6,
528 E7,
529 E8,
530 E9,
531 E10,
532 E11,
533 E12,
534 E13,
535 >
536 where
537 E5A: Display + Debug + Send + Sync + 'static,
538 {
539 ContractWrapper {
540 execute_fn: self.execute_fn,
541 instantiate_fn: self.instantiate_fn,
542 query_fn: self.query_fn,
543 sudo_fn: self.sudo_fn,
544 reply_fn: Some(Box::new(reply_fn)),
545 migrate_fn: self.migrate_fn,
546 checksum: None,
547
548 channel_open_fn: self.channel_open_fn,
549 channel_connect_fn: self.channel_connect_fn,
550 channel_close_fn: self.channel_close_fn,
551
552 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
553 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
554 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
555
556 ibc_source_callback: self.ibc_source_callback,
557 }
558 }
559
560 pub fn with_reply_empty<E5A>(
562 self,
563 reply_fn: ReplyFn<Empty, E5A, Empty>,
564 ) -> ContractWrapper<
565 T1,
566 T2,
567 T3,
568 E1,
569 E2,
570 E3,
571 C,
572 Q,
573 T4,
574 E4,
575 E5A,
576 T6,
577 E6,
578 E7,
579 E8,
580 E9,
581 E10,
582 E11,
583 E12,
584 E13,
585 >
586 where
587 E5A: Display + Debug + Send + Sync + 'static,
588 {
589 ContractWrapper {
590 execute_fn: self.execute_fn,
591 instantiate_fn: self.instantiate_fn,
592 query_fn: self.query_fn,
593 sudo_fn: self.sudo_fn,
594 reply_fn: Some(customize_permissioned_fn(reply_fn)),
595 migrate_fn: self.migrate_fn,
596 checksum: None,
597
598 channel_open_fn: self.channel_open_fn,
599 channel_connect_fn: self.channel_connect_fn,
600 channel_close_fn: self.channel_close_fn,
601
602 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
603 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
604 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
605
606 ibc_source_callback: self.ibc_source_callback,
607 }
608 }
609
610 pub fn with_migrate<T6A, E6A>(
612 self,
613 migrate_fn: PermissionedFn<T6A, C, E6A, Q>,
614 ) -> ContractWrapper<
615 T1,
616 T2,
617 T3,
618 E1,
619 E2,
620 E3,
621 C,
622 Q,
623 T4,
624 E4,
625 E5,
626 T6A,
627 E6A,
628 E7,
629 E8,
630 E9,
631 E10,
632 E11,
633 E12,
634 E13,
635 >
636 where
637 T6A: DeserializeOwned + 'static,
638 E6A: Display + Debug + Send + Sync + 'static,
639 {
640 ContractWrapper {
641 execute_fn: self.execute_fn,
642 instantiate_fn: self.instantiate_fn,
643 query_fn: self.query_fn,
644 sudo_fn: self.sudo_fn,
645 reply_fn: self.reply_fn,
646 migrate_fn: Some(Box::new(migrate_fn)),
647 checksum: None,
648
649 channel_open_fn: self.channel_open_fn,
650 channel_connect_fn: self.channel_connect_fn,
651 channel_close_fn: self.channel_close_fn,
652
653 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
654 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
655 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
656
657 ibc_source_callback: self.ibc_source_callback,
658 }
659 }
660
661 pub fn with_migrate_empty<T6A, E6A>(
663 self,
664 migrate_fn: PermissionedFn<T6A, Empty, E6A, Empty>,
665 ) -> ContractWrapper<
666 T1,
667 T2,
668 T3,
669 E1,
670 E2,
671 E3,
672 C,
673 Q,
674 T4,
675 E4,
676 E5,
677 T6A,
678 E6A,
679 E7,
680 E8,
681 E9,
682 E10,
683 E11,
684 E12,
685 E13,
686 >
687 where
688 T6A: DeserializeOwned + 'static,
689 E6A: Display + Debug + Send + Sync + 'static,
690 {
691 ContractWrapper {
692 execute_fn: self.execute_fn,
693 instantiate_fn: self.instantiate_fn,
694 query_fn: self.query_fn,
695 sudo_fn: self.sudo_fn,
696 reply_fn: self.reply_fn,
697 migrate_fn: Some(customize_permissioned_fn(migrate_fn)),
698 checksum: None,
699
700 channel_open_fn: self.channel_open_fn,
701 channel_connect_fn: self.channel_connect_fn,
702 channel_close_fn: self.channel_close_fn,
703
704 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
705 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
706 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
707
708 ibc_source_callback: self.ibc_source_callback,
709 }
710 }
711
712 pub fn with_checksum(mut self, checksum: Checksum) -> Self {
714 self.checksum = Some(checksum);
715 self
716 }
717
718 pub fn with_ibc<E7A, E8A, E9A, E10A, E11A, E12A>(
720 self,
721 channel_open_fn: IbcFn<IbcChannelOpenMsg, IbcChannelOpenResponse, E7A, Q>,
722 channel_connect_fn: IbcFn<IbcChannelConnectMsg, IbcBasicResponse<C>, E8A, Q>,
723 channel_close_fn: IbcFn<IbcChannelCloseMsg, IbcBasicResponse<C>, E9A, Q>,
724
725 ibc_packet_receive_fn: IbcFn<IbcPacketReceiveMsg, IbcReceiveResponse<C>, E10A, Q>,
726 ibc_packet_ack_fn: IbcFn<IbcPacketAckMsg, IbcBasicResponse<C>, E11A, Q>,
727 ibc_packet_timeout_fn: IbcFn<IbcPacketTimeoutMsg, IbcBasicResponse<C>, E12A, Q>,
728 ) -> ContractWrapper<
729 T1,
730 T2,
731 T3,
732 E1,
733 E2,
734 E3,
735 C,
736 Q,
737 T4,
738 E4,
739 E5,
740 T6,
741 E6,
742 E7A,
743 E8A,
744 E9A,
745 E10A,
746 E11A,
747 E12A,
748 E13,
749 >
750 where
751 E7A: Display + Debug + Send + Sync + 'static,
752 E8A: Display + Debug + Send + Sync + 'static,
753 E9A: Display + Debug + Send + Sync + 'static,
754 E10A: Display + Debug + Send + Sync + 'static,
755 E11A: Display + Debug + Send + Sync + 'static,
756 E12A: Display + Debug + Send + Sync + 'static,
757 {
758 ContractWrapper {
759 execute_fn: self.execute_fn,
760 instantiate_fn: self.instantiate_fn,
761 query_fn: self.query_fn,
762 sudo_fn: self.sudo_fn,
763 reply_fn: self.reply_fn,
764 migrate_fn: self.migrate_fn,
765 checksum: None,
766
767 channel_open_fn: Some(Box::new(channel_open_fn)),
768 channel_connect_fn: Some(Box::new(channel_connect_fn)),
769 channel_close_fn: Some(Box::new(channel_close_fn)),
770
771 ibc_packet_receive_fn: Some(Box::new(ibc_packet_receive_fn)),
772 ibc_packet_ack_fn: Some(Box::new(ibc_packet_ack_fn)),
773 ibc_packet_timeout_fn: Some(Box::new(ibc_packet_timeout_fn)),
774
775 ibc_source_callback: self.ibc_source_callback,
776 }
777 }
778 pub fn with_ibc_source_callback<E13A>(
780 self,
781 ibc_source_callback: IbcFn<IbcSourceCallbackMsg, IbcBasicResponse<C>, E13A, Q>,
782 ) -> ContractWrapper<
783 T1,
784 T2,
785 T3,
786 E1,
787 E2,
788 E3,
789 C,
790 Q,
791 T4,
792 E4,
793 E5,
794 T6,
795 E6,
796 E7,
797 E8,
798 E9,
799 E10,
800 E11,
801 E12,
802 E13A,
803 >
804 where
805 E13A: Display + Debug + Send + Sync + 'static,
806 {
807 ContractWrapper {
808 execute_fn: self.execute_fn,
809 instantiate_fn: self.instantiate_fn,
810 query_fn: self.query_fn,
811 sudo_fn: self.sudo_fn,
812 reply_fn: self.reply_fn,
813 migrate_fn: self.migrate_fn,
814 checksum: None,
815
816 channel_open_fn: self.channel_open_fn,
817 channel_connect_fn: self.channel_connect_fn,
818 channel_close_fn: self.channel_close_fn,
819
820 ibc_packet_receive_fn: self.ibc_packet_receive_fn,
821 ibc_packet_ack_fn: self.ibc_packet_ack_fn,
822 ibc_packet_timeout_fn: self.ibc_packet_timeout_fn,
823
824 ibc_source_callback: Some(Box::new(ibc_source_callback)),
825 }
826 }
827}
828
829fn customize_contract_fn<T, C, E, Q>(
830 raw_fn: ContractFn<T, Empty, E, Empty>,
831) -> ContractClosure<T, C, E, Q>
832where
833 T: DeserializeOwned + 'static,
834 E: Display + Debug + Send + Sync + 'static,
835 C: CustomMsg,
836 Q: CustomQuery + DeserializeOwned,
837{
838 Box::new(
839 move |mut deps: DepsMut<Q>,
840 env: Env,
841 info: MessageInfo,
842 msg: T|
843 -> Result<Response<C>, E> {
844 let deps = decustomize_deps_mut(&mut deps);
845 raw_fn(deps, env, info, msg).map(customize_response::<C>)
846 },
847 )
848}
849
850fn customize_query_fn<T, E, Q>(raw_fn: QueryFn<T, E, Empty>) -> QueryClosure<T, E, Q>
851where
852 T: DeserializeOwned + 'static,
853 E: Display + Debug + Send + Sync + 'static,
854 Q: CustomQuery + DeserializeOwned,
855{
856 Box::new(
857 move |deps: Deps<Q>, env: Env, msg: T| -> Result<Binary, E> {
858 let deps = decustomize_deps(&deps);
859 raw_fn(deps, env, msg)
860 },
861 )
862}
863
864fn customize_permissioned_fn<T, C, E, Q>(
865 raw_fn: PermissionedFn<T, Empty, E, Empty>,
866) -> PermissionedClosure<T, C, E, Q>
867where
868 T: DeserializeOwned + 'static,
869 E: Display + Debug + Send + Sync + 'static,
870 C: CustomMsg,
871 Q: CustomQuery + DeserializeOwned,
872{
873 Box::new(
874 move |mut deps: DepsMut<Q>, env: Env, msg: T| -> Result<Response<C>, E> {
875 let deps = decustomize_deps_mut(&mut deps);
876 raw_fn(deps, env, msg).map(customize_response::<C>)
877 },
878 )
879}
880
881fn decustomize_deps_mut<'a, Q>(deps: &'a mut DepsMut<Q>) -> DepsMut<'a, Empty>
882where
883 Q: CustomQuery + DeserializeOwned,
884{
885 DepsMut {
886 storage: deps.storage,
887 api: deps.api,
888 querier: QuerierWrapper::new(deps.querier.deref()),
889 }
890}
891
892fn decustomize_deps<'a, Q>(deps: &'a Deps<'a, Q>) -> Deps<'a, Empty>
893where
894 Q: CustomQuery + DeserializeOwned,
895{
896 Deps {
897 storage: deps.storage,
898 api: deps.api,
899 querier: QuerierWrapper::new(deps.querier.deref()),
900 }
901}
902
903fn customize_response<C>(resp: Response<Empty>) -> Response<C>
904where
905 C: CustomMsg,
906{
907 let mut customized_resp = Response::<C>::new()
908 .add_submessages(resp.messages.into_iter().map(customize_msg::<C>))
909 .add_events(resp.events)
910 .add_attributes(resp.attributes);
911 customized_resp.data = resp.data;
912 customized_resp
913}
914
915fn customize_msg<C>(msg: SubMsg<Empty>) -> SubMsg<C>
916where
917 C: CustomMsg,
918{
919 SubMsg {
920 id: msg.id,
921 payload: msg.payload,
922 msg: match msg.msg {
923 CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm),
924 CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank),
925 #[cfg(feature = "staking")]
926 CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking),
927 #[cfg(feature = "staking")]
928 CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution),
929 CosmosMsg::Custom(_) => unreachable!(),
930 #[cfg(feature = "stargate")]
931 CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc),
932 #[cfg(feature = "cosmwasm_2_0")]
933 CosmosMsg::Any(any) => CosmosMsg::Any(any),
934 other => panic!("unknown message variant {:?}", other),
935 },
936 gas_limit: msg.gas_limit,
937 reply_on: msg.reply_on,
938 }
939}
940
941impl<T1, T2, T3, E1, E2, E3, C, T4, E4, E5, T6, E6, E7, E8, E9, E10, E11, E12, E13, Q>
942 Contract<C, Q>
943 for ContractWrapper<
944 T1,
945 T2,
946 T3,
947 E1,
948 E2,
949 E3,
950 C,
951 Q,
952 T4,
953 E4,
954 E5,
955 T6,
956 E6,
957 E7,
958 E8,
959 E9,
960 E10,
961 E11,
962 E12,
963 E13,
964 >
965where
966 T1: DeserializeOwned, T2: DeserializeOwned, T3: DeserializeOwned, T4: DeserializeOwned, T6: DeserializeOwned, E1: Display + Debug + Send + Sync + 'static, E2: Display + Debug + Send + Sync + 'static, E3: Display + Debug + Send + Sync + 'static, E4: Display + Debug + Send + Sync + 'static, E5: Display + Debug + Send + Sync + 'static, E6: Display + Debug + Send + Sync + 'static, E7: Display + Debug + Send + Sync + 'static, E8: Display + Debug + Send + Sync + 'static, E9: Display + Debug + Send + Sync + 'static, E10: Display + Debug + Send + Sync + 'static, E11: Display + Debug + Send + Sync + 'static, E12: Display + Debug + Send + Sync + 'static, E13: Display + Debug + Send + Sync + 'static, C: CustomMsg, Q: CustomQuery + DeserializeOwned, {
987 fn execute(
991 &self,
992 deps: DepsMut<Q>,
993 env: Env,
994 info: MessageInfo,
995 msg: Vec<u8>,
996 ) -> AnyResult<Response<C>> {
997 let msg: T1 = from_json(msg)?;
998 (self.execute_fn)(deps, env, info, msg).map_err(|err: E1| anyhow!(err))
999 }
1000
1001 fn instantiate(
1005 &self,
1006 deps: DepsMut<Q>,
1007 env: Env,
1008 info: MessageInfo,
1009 msg: Vec<u8>,
1010 ) -> AnyResult<Response<C>> {
1011 let msg: T2 = from_json(msg)?;
1012 (self.instantiate_fn)(deps, env, info, msg).map_err(|err: E2| anyhow!(err))
1013 }
1014
1015 fn query(&self, deps: Deps<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Binary> {
1019 let msg: T3 = from_json(msg)?;
1020 (self.query_fn)(deps, env, msg).map_err(|err: E3| anyhow!(err))
1021 }
1022
1023 fn sudo(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>> {
1028 let msg: T4 = from_json(msg)?;
1029 match &self.sudo_fn {
1030 Some(sudo) => sudo(deps, env, msg).map_err(|err: E4| anyhow!(err)),
1031 None => bail!("sudo is not implemented for contract"),
1032 }
1033 }
1034
1035 fn reply(&self, deps: DepsMut<Q>, env: Env, reply_data: Reply) -> AnyResult<Response<C>> {
1040 let msg: Reply = reply_data;
1041 match &self.reply_fn {
1042 Some(reply) => reply(deps, env, msg).map_err(|err: E5| anyhow!(err)),
1043 None => bail!("reply is not implemented for contract"),
1044 }
1045 }
1046
1047 fn migrate(&self, deps: DepsMut<Q>, env: Env, msg: Vec<u8>) -> AnyResult<Response<C>> {
1052 let msg: T6 = from_json(msg)?;
1053 match &self.migrate_fn {
1054 Some(migrate) => migrate(deps, env, msg).map_err(|err: E6| anyhow!(err)),
1055 None => bail!("migrate is not implemented for contract"),
1056 }
1057 }
1058
1059 fn checksum(&self) -> Option<Checksum> {
1061 self.checksum
1062 }
1063
1064 fn ibc_channel_open(
1065 &self,
1066 deps: DepsMut<Q>,
1067 env: Env,
1068 msg: IbcChannelOpenMsg,
1069 ) -> AnyResult<IbcChannelOpenResponse> {
1070 match &self.channel_open_fn {
1071 Some(channel_open) => channel_open(deps, env, msg).map_err(|err| anyhow!(err)),
1072 None => bail!("channel open not implemented for contract"),
1073 }
1074 }
1075 fn ibc_channel_connect(
1076 &self,
1077 deps: DepsMut<Q>,
1078 env: Env,
1079 msg: IbcChannelConnectMsg,
1080 ) -> AnyResult<IbcBasicResponse<C>> {
1081 match &self.channel_connect_fn {
1082 Some(channel_connect) => channel_connect(deps, env, msg).map_err(|err| anyhow!(err)),
1083 None => bail!("channel connect not implemented for contract"),
1084 }
1085 }
1086 fn ibc_channel_close(
1087 &self,
1088 deps: DepsMut<Q>,
1089 env: Env,
1090 msg: IbcChannelCloseMsg,
1091 ) -> AnyResult<IbcBasicResponse<C>> {
1092 match &self.channel_close_fn {
1093 Some(channel_close) => channel_close(deps, env, msg).map_err(|err| anyhow!(err)),
1094 None => bail!("channel close not implemented for contract"),
1095 }
1096 }
1097
1098 fn ibc_packet_receive(
1099 &self,
1100 deps: DepsMut<Q>,
1101 env: Env,
1102 msg: IbcPacketReceiveMsg,
1103 ) -> AnyResult<IbcReceiveResponse<C>> {
1104 match &self.ibc_packet_receive_fn {
1105 Some(packet_receive) => packet_receive(deps, env, msg).map_err(|err| anyhow!(err)),
1106 None => bail!("packet receive not implemented for contract"),
1107 }
1108 }
1109 fn ibc_packet_acknowledge(
1110 &self,
1111 deps: DepsMut<Q>,
1112 env: Env,
1113 msg: IbcPacketAckMsg,
1114 ) -> AnyResult<IbcBasicResponse<C>> {
1115 match &self.ibc_packet_ack_fn {
1116 Some(packet_ack) => packet_ack(deps, env, msg).map_err(|err| anyhow!(err)),
1117 None => bail!("packet ack not implemented for contract"),
1118 }
1119 }
1120 fn ibc_packet_timeout(
1121 &self,
1122 deps: DepsMut<Q>,
1123 env: Env,
1124 msg: IbcPacketTimeoutMsg,
1125 ) -> AnyResult<IbcBasicResponse<C>> {
1126 match &self.ibc_packet_timeout_fn {
1127 Some(packet_timeout) => packet_timeout(deps, env, msg).map_err(|err| anyhow!(err)),
1128 None => bail!("packet timeout not implemented for contract"),
1129 }
1130 }
1131
1132 fn ibc_source_callback(
1133 &self,
1134 deps: DepsMut<Q>,
1135 env: Env,
1136 msg: IbcSourceCallbackMsg,
1137 ) -> AnyResult<IbcBasicResponse<C>> {
1138 match &self.ibc_source_callback {
1139 Some(ibc_source_callback) => {
1140 ibc_source_callback(deps, env, msg).map_err(|err| anyhow!(err))
1141 }
1142 None => bail!("ibc source callback not implemented for contract"),
1143 }
1144 }
1145}