1use crate::wasm_emulation::channel::RemoteChannel;
4use crate::{
5 App, Bank, BankKeeper, Distribution, DistributionKeeper, FailingModule, Gov, GovFailingModule,
6 Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Wasm, WasmKeeper,
7};
8use anyhow::Result as AnyResult;
9use cosmwasm_std::testing::{mock_env, MockApi, MockStorage};
10use cosmwasm_std::{Api, BlockInfo, CustomMsg, CustomQuery, Empty, Storage};
11use serde::de::DeserializeOwned;
12use std::fmt::Debug;
13
14pub type BasicAppBuilder<ExecC, QueryC> = AppBuilder<
30 BankKeeper,
31 MockApi,
32 MockStorage,
33 FailingModule<ExecC, QueryC, Empty>,
34 WasmKeeper<ExecC, QueryC>,
35 StakeKeeper,
36 DistributionKeeper,
37 IbcFailingModule,
38 GovFailingModule,
39>;
40
41pub struct AppBuilder<Bank, Api, Storage, Custom, Wasm, Staking, Distr, Ibc, Gov> {
44 api: Api,
45 block: BlockInfo,
46 storage: Storage,
47 bank: Bank,
48 wasm: Wasm,
49 custom: Custom,
50 staking: Staking,
51 distribution: Distr,
52 ibc: Ibc,
53 gov: Gov,
54 remote: Option<RemoteChannel>,
55}
56
57impl Default
58 for AppBuilder<
59 BankKeeper,
60 MockApi,
61 MockStorage,
62 FailingModule<Empty, Empty, Empty>,
63 WasmKeeper<Empty, Empty>,
64 StakeKeeper,
65 DistributionKeeper,
66 IbcFailingModule,
67 GovFailingModule,
68 >
69{
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl
76 AppBuilder<
77 BankKeeper,
78 MockApi,
79 MockStorage,
80 FailingModule<Empty, Empty, Empty>,
81 WasmKeeper<Empty, Empty>,
82 StakeKeeper,
83 DistributionKeeper,
84 IbcFailingModule,
85 GovFailingModule,
86 >
87{
88 pub fn new() -> Self {
90 AppBuilder {
91 api: MockApi::default(),
92 block: mock_env().block,
93 storage: MockStorage::new(),
94 bank: BankKeeper::new(),
95 wasm: WasmKeeper::new(),
96 custom: FailingModule::new("custom"),
97 staking: StakeKeeper::new(),
98 distribution: DistributionKeeper::new(),
99 ibc: IbcFailingModule::new("ibc"),
100 gov: GovFailingModule::new("gov"),
101 remote: None,
102 }
103 }
104}
105
106impl<ExecC, QueryC>
107 AppBuilder<
108 BankKeeper,
109 MockApi,
110 MockStorage,
111 FailingModule<ExecC, QueryC, Empty>,
112 WasmKeeper<ExecC, QueryC>,
113 StakeKeeper,
114 DistributionKeeper,
115 IbcFailingModule,
116 GovFailingModule,
117 >
118where
119 ExecC: CustomMsg + DeserializeOwned + 'static,
120 QueryC: Debug + CustomQuery + DeserializeOwned + 'static,
121{
122 pub fn new_custom() -> Self {
125 AppBuilder {
126 api: MockApi::default(),
127 block: mock_env().block,
128 storage: MockStorage::new(),
129 bank: BankKeeper::new(),
130 wasm: WasmKeeper::new(),
131 custom: FailingModule::new("custom"),
132 staking: StakeKeeper::new(),
133 distribution: DistributionKeeper::new(),
134 ibc: IbcFailingModule::new("ibc"),
135 gov: GovFailingModule::new("gov"),
136 remote: None,
137 }
138 }
139}
140
141impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT>
142 AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT>
143where
144 CustomT: Module,
145 WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
146 CustomT::QueryT: CustomQuery,
147{
148 pub fn with_wasm<NewWasm: Wasm<CustomT::ExecT, CustomT::QueryT>>(
154 self,
155 wasm: NewWasm,
156 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, NewWasm, StakingT, DistrT, IbcT, GovT> {
157 let AppBuilder {
158 bank,
159 api,
160 storage,
161 custom,
162 block,
163 staking,
164 distribution,
165 ibc,
166 gov,
167 remote,
168 ..
169 } = self;
170
171 AppBuilder {
172 api,
173 block,
174 storage,
175 bank,
176 wasm,
177 custom,
178 staking,
179 distribution,
180 ibc,
181 gov,
182 remote,
183 }
184 }
185
186 pub fn with_bank<NewBank: Bank>(
188 self,
189 bank: NewBank,
190 ) -> AppBuilder<NewBank, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT> {
191 let AppBuilder {
192 wasm,
193 api,
194 storage,
195 custom,
196 block,
197 staking,
198 distribution,
199 ibc,
200 gov,
201 remote,
202 ..
203 } = self;
204
205 AppBuilder {
206 api,
207 block,
208 storage,
209 bank,
210 wasm,
211 custom,
212 staking,
213 distribution,
214 ibc,
215 gov,
216 remote,
217 }
218 }
219
220 pub fn with_api<NewApi: Api>(
222 self,
223 api: NewApi,
224 ) -> AppBuilder<BankT, NewApi, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT> {
225 let AppBuilder {
226 wasm,
227 bank,
228 storage,
229 custom,
230 block,
231 staking,
232 distribution,
233 ibc,
234 gov,
235 remote,
236 ..
237 } = self;
238
239 AppBuilder {
240 api,
241 block,
242 storage,
243 bank,
244 wasm,
245 custom,
246 staking,
247 distribution,
248 ibc,
249 gov,
250 remote,
251 }
252 }
253
254 pub fn with_storage<NewStorage: Storage>(
256 self,
257 storage: NewStorage,
258 ) -> AppBuilder<BankT, ApiT, NewStorage, CustomT, WasmT, StakingT, DistrT, IbcT, GovT> {
259 let AppBuilder {
260 wasm,
261 api,
262 bank,
263 custom,
264 block,
265 staking,
266 distribution,
267 ibc,
268 gov,
269 remote,
270 ..
271 } = self;
272
273 AppBuilder {
274 api,
275 block,
276 storage,
277 bank,
278 wasm,
279 custom,
280 staking,
281 distribution,
282 ibc,
283 gov,
284 remote,
285 }
286 }
287
288 pub fn with_custom<NewCustom: Module>(
294 self,
295 custom: NewCustom,
296 ) -> AppBuilder<BankT, ApiT, StorageT, NewCustom, WasmT, StakingT, DistrT, IbcT, GovT> {
297 let AppBuilder {
298 wasm,
299 bank,
300 api,
301 storage,
302 block,
303 staking,
304 distribution,
305 ibc,
306 gov,
307 remote,
308 ..
309 } = self;
310
311 AppBuilder {
312 api,
313 block,
314 storage,
315 bank,
316 wasm,
317 custom,
318 staking,
319 distribution,
320 ibc,
321 gov,
322 remote,
323 }
324 }
325
326 pub fn with_staking<NewStaking: Staking>(
328 self,
329 staking: NewStaking,
330 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, NewStaking, DistrT, IbcT, GovT> {
331 let AppBuilder {
332 wasm,
333 api,
334 storage,
335 custom,
336 block,
337 bank,
338 distribution,
339 ibc,
340 gov,
341 remote,
342 ..
343 } = self;
344
345 AppBuilder {
346 api,
347 block,
348 storage,
349 bank,
350 wasm,
351 custom,
352 staking,
353 distribution,
354 ibc,
355 gov,
356 remote,
357 }
358 }
359
360 pub fn with_distribution<NewDistribution: Distribution>(
362 self,
363 distribution: NewDistribution,
364 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, NewDistribution, IbcT, GovT>
365 {
366 let AppBuilder {
367 wasm,
368 api,
369 storage,
370 custom,
371 block,
372 staking,
373 bank,
374 ibc,
375 gov,
376 remote,
377 ..
378 } = self;
379
380 AppBuilder {
381 api,
382 block,
383 storage,
384 bank,
385 wasm,
386 custom,
387 staking,
388 distribution,
389 ibc,
390 gov,
391 remote,
392 }
393 }
394
395 pub fn with_ibc<NewIbc: Ibc>(
403 self,
404 ibc: NewIbc,
405 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, NewIbc, GovT> {
406 let AppBuilder {
407 wasm,
408 api,
409 storage,
410 custom,
411 block,
412 staking,
413 bank,
414 distribution,
415 gov,
416 remote,
417 ..
418 } = self;
419
420 AppBuilder {
421 api,
422 block,
423 storage,
424 bank,
425 wasm,
426 custom,
427 staking,
428 distribution,
429 ibc,
430 gov,
431 remote,
432 }
433 }
434
435 pub fn with_gov<NewGov: Gov>(
437 self,
438 gov: NewGov,
439 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, NewGov> {
440 let AppBuilder {
441 wasm,
442 api,
443 storage,
444 custom,
445 block,
446 staking,
447 bank,
448 distribution,
449 ibc,
450 remote,
451 ..
452 } = self;
453
454 AppBuilder {
455 api,
456 block,
457 storage,
458 bank,
459 wasm,
460 custom,
461 staking,
462 distribution,
463 ibc,
464 gov,
465 remote,
466 }
467 }
468
469 pub fn with_remote(
471 self,
472 remote: RemoteChannel,
473 ) -> AppBuilder<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT> {
474 let AppBuilder {
475 wasm,
476 api,
477 storage,
478 custom,
479 block,
480 staking,
481 bank,
482 distribution,
483 ibc,
484 gov,
485 ..
486 } = self;
487
488 AppBuilder {
489 api,
490 block,
491 storage,
492 bank,
493 wasm,
494 custom,
495 staking,
496 distribution,
497 ibc,
498 remote: Some(remote),
499 gov,
500 }
501 }
502
503 pub fn with_block(mut self, block: BlockInfo) -> Self {
505 self.block = block;
506 self
507 }
508
509 #[allow(clippy::type_complexity)]
510 pub fn build<F>(
514 self,
515 init_fn: F,
516 ) -> AnyResult<App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT>>
517 where
518 BankT: Bank,
519 ApiT: Api,
520 StorageT: Storage,
521 CustomT: Module,
522 WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
523 StakingT: Staking,
524 DistrT: Distribution,
525 IbcT: Ibc,
526 GovT: Gov,
527 F: FnOnce(
528 &mut Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT>,
529 &dyn Api,
530 &mut dyn Storage,
531 ),
532 {
533 let router = Router {
534 wasm: self.wasm,
535 bank: self.bank,
536 custom: self.custom,
537 staking: self.staking,
538 distribution: self.distribution,
539 ibc: self.ibc,
540 gov: self.gov,
541 };
542
543 let mut app = App {
544 router,
545 api: self.api,
546 block: self.block,
547 storage: self.storage,
548 remote: self.remote.ok_or(anyhow::anyhow!(
549 "Remote has to be defined to use clone-testing"
550 ))?,
551 };
552 app.init_modules(init_fn);
553 Ok(app)
554 }
555}