@@ -33,6 +33,8 @@ use crate::timestamp::Timestamp;
33
33
use crate :: traits:: { Api , Querier , QuerierResult } ;
34
34
use crate :: types:: { BlockInfo , ContractInfo , Env , MessageInfo , TransactionInfo } ;
35
35
use crate :: Attribute ;
36
+ #[ cfg( feature = "stargate" ) ]
37
+ use crate :: { ChannelResponse , IbcQuery , ListChannelsResponse , PortIdResponse } ;
36
38
37
39
use super :: riffle_shuffle;
38
40
@@ -435,6 +437,8 @@ pub struct MockQuerier<C: DeserializeOwned = Empty> {
435
437
#[ cfg( feature = "staking" ) ]
436
438
staking : StakingQuerier ,
437
439
wasm : WasmQuerier ,
440
+ #[ cfg( feature = "stargate" ) ]
441
+ ibc : IbcQuerier ,
438
442
/// A handler to handle custom queries. This is set to a dummy handler that
439
443
/// always errors by default. Update it via `with_custom_handler`.
440
444
///
@@ -449,6 +453,8 @@ impl<C: DeserializeOwned> MockQuerier<C> {
449
453
#[ cfg( feature = "staking" ) ]
450
454
staking : StakingQuerier :: default ( ) ,
451
455
wasm : WasmQuerier :: default ( ) ,
456
+ #[ cfg( feature = "stargate" ) ]
457
+ ibc : IbcQuerier :: default ( ) ,
452
458
// strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365
453
459
custom_handler : Box :: from ( |_: & _ | -> MockQuerierCustomHandlerResult {
454
460
SystemResult :: Err ( SystemError :: UnsupportedRequest {
@@ -477,6 +483,11 @@ impl<C: DeserializeOwned> MockQuerier<C> {
477
483
self . staking = StakingQuerier :: new ( denom, validators, delegations) ;
478
484
}
479
485
486
+ #[ cfg( feature = "stargate" ) ]
487
+ pub fn update_ibc ( & mut self , port_id : & str , channels : & [ IbcChannel ] ) {
488
+ self . ibc = IbcQuerier :: new ( port_id, channels) ;
489
+ }
490
+
480
491
pub fn update_wasm < WH : ' static > ( & mut self , handler : WH )
481
492
where
482
493
WH : Fn ( & WasmQuery ) -> QuerierResult ,
@@ -527,9 +538,7 @@ impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
527
538
kind : "Stargate" . to_string ( ) ,
528
539
} ) ,
529
540
#[ cfg( feature = "stargate" ) ]
530
- QueryRequest :: Ibc ( _) => SystemResult :: Err ( SystemError :: UnsupportedRequest {
531
- kind : "Ibc" . to_string ( ) ,
532
- } ) ,
541
+ QueryRequest :: Ibc ( msg) => self . ibc . query ( msg) ,
533
542
}
534
543
}
535
544
}
@@ -675,6 +684,70 @@ impl BankQuerier {
675
684
}
676
685
}
677
686
687
+ #[ cfg( feature = "stargate" ) ]
688
+ #[ derive( Clone , Default ) ]
689
+ pub struct IbcQuerier {
690
+ port_id : String ,
691
+ channels : Vec < IbcChannel > ,
692
+ }
693
+
694
+ #[ cfg( feature = "stargate" ) ]
695
+ impl IbcQuerier {
696
+ /// Create a mock querier where:
697
+ /// - port_id is the port the "contract" is bound to
698
+ /// - channels are a list of ibc channels
699
+ pub fn new ( port_id : & str , channels : & [ IbcChannel ] ) -> Self {
700
+ IbcQuerier {
701
+ port_id : port_id. to_string ( ) ,
702
+ channels : channels. to_vec ( ) ,
703
+ }
704
+ }
705
+
706
+ pub fn query ( & self , request : & IbcQuery ) -> QuerierResult {
707
+ let contract_result: ContractResult < Binary > = match request {
708
+ IbcQuery :: Channel {
709
+ channel_id,
710
+ port_id,
711
+ } => {
712
+ let channel = self
713
+ . channels
714
+ . iter ( )
715
+ . find ( |c| match port_id {
716
+ Some ( p) => c. endpoint . channel_id . eq ( channel_id) && c. endpoint . port_id . eq ( p) ,
717
+ None => {
718
+ c. endpoint . channel_id . eq ( channel_id)
719
+ && c. endpoint . port_id == self . port_id
720
+ }
721
+ } )
722
+ . cloned ( ) ;
723
+ let res = ChannelResponse { channel } ;
724
+ to_binary ( & res) . into ( )
725
+ }
726
+ IbcQuery :: ListChannels { port_id } => {
727
+ let channels = self
728
+ . channels
729
+ . iter ( )
730
+ . filter ( |c| match port_id {
731
+ Some ( p) => c. endpoint . port_id . eq ( p) ,
732
+ None => c. endpoint . port_id == self . port_id ,
733
+ } )
734
+ . cloned ( )
735
+ . collect ( ) ;
736
+ let res = ListChannelsResponse { channels } ;
737
+ to_binary ( & res) . into ( )
738
+ }
739
+ IbcQuery :: PortId { } => {
740
+ let res = PortIdResponse {
741
+ port_id : self . port_id . clone ( ) ,
742
+ } ;
743
+ to_binary ( & res) . into ( )
744
+ }
745
+ } ;
746
+ // system result is always ok in the mock implementation
747
+ SystemResult :: Ok ( contract_result)
748
+ }
749
+ }
750
+
678
751
#[ cfg( feature = "staking" ) ]
679
752
#[ derive( Clone , Default ) ]
680
753
pub struct StakingQuerier {
@@ -1189,6 +1262,118 @@ mod tests {
1189
1262
assert_eq ! ( res. amount, coin( 0 , "ELF" ) ) ;
1190
1263
}
1191
1264
1265
+ #[ cfg( feature = "stargate" ) ]
1266
+ #[ test]
1267
+ fn ibc_querier_channel_existing ( ) {
1268
+ let chan1 = mock_ibc_channel ( "channel-0" , IbcOrder :: Ordered , "ibc" ) ;
1269
+ let chan2 = mock_ibc_channel ( "channel-1" , IbcOrder :: Ordered , "ibc" ) ;
1270
+
1271
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1. clone ( ) , chan2] ) ;
1272
+
1273
+ // query existing
1274
+ let query = & IbcQuery :: Channel {
1275
+ channel_id : "channel-0" . to_string ( ) ,
1276
+ port_id : Some ( "my_port" . to_string ( ) ) ,
1277
+ } ;
1278
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1279
+ let chan: ChannelResponse = from_binary ( & raw ) . unwrap ( ) ;
1280
+ assert_eq ! ( chan. channel, Some ( chan1) ) ;
1281
+ }
1282
+
1283
+ #[ cfg( feature = "stargate" ) ]
1284
+ #[ test]
1285
+ fn ibc_querier_channel_existing_no_port ( ) {
1286
+ let chan1 = IbcChannel {
1287
+ endpoint : IbcEndpoint {
1288
+ port_id : "myport" . to_string ( ) ,
1289
+ channel_id : "channel-0" . to_string ( ) ,
1290
+ } ,
1291
+ counterparty_endpoint : IbcEndpoint {
1292
+ port_id : "their_port" . to_string ( ) ,
1293
+ channel_id : "channel-7" . to_string ( ) ,
1294
+ } ,
1295
+ order : IbcOrder :: Ordered ,
1296
+ version : "ibc" . to_string ( ) ,
1297
+ connection_id : "connection-2" . to_string ( ) ,
1298
+ } ;
1299
+ let chan2 = mock_ibc_channel ( "channel-1" , IbcOrder :: Ordered , "ibc" ) ;
1300
+
1301
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1. clone ( ) , chan2] ) ;
1302
+
1303
+ // query existing
1304
+ let query = & IbcQuery :: Channel {
1305
+ channel_id : "channel-0" . to_string ( ) ,
1306
+ port_id : Some ( "myport" . to_string ( ) ) ,
1307
+ } ;
1308
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1309
+ let chan: ChannelResponse = from_binary ( & raw ) . unwrap ( ) ;
1310
+ assert_eq ! ( chan. channel, Some ( chan1) ) ;
1311
+ }
1312
+
1313
+ #[ cfg( feature = "stargate" ) ]
1314
+ #[ test]
1315
+ fn ibc_querier_channel_none ( ) {
1316
+ let chan1 = mock_ibc_channel ( "channel-0" , IbcOrder :: Ordered , "ibc" ) ;
1317
+ let chan2 = mock_ibc_channel ( "channel-1" , IbcOrder :: Ordered , "ibc" ) ;
1318
+
1319
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1, chan2] ) ;
1320
+
1321
+ // query non-existing
1322
+ let query = & IbcQuery :: Channel {
1323
+ channel_id : "channel-0" . to_string ( ) ,
1324
+ port_id : None ,
1325
+ } ;
1326
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1327
+ let chan: ChannelResponse = from_binary ( & raw ) . unwrap ( ) ;
1328
+ assert_eq ! ( chan. channel, None ) ;
1329
+ }
1330
+
1331
+ #[ cfg( feature = "stargate" ) ]
1332
+ #[ test]
1333
+ fn ibc_querier_channels_matching ( ) {
1334
+ let chan1 = mock_ibc_channel ( "channel-0" , IbcOrder :: Ordered , "ibc" ) ;
1335
+ let chan2 = mock_ibc_channel ( "channel-1" , IbcOrder :: Ordered , "ibc" ) ;
1336
+
1337
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1. clone ( ) , chan2. clone ( ) ] ) ;
1338
+
1339
+ // query channels matching "my_port" (should match both above)
1340
+ let query = & & IbcQuery :: ListChannels {
1341
+ port_id : Some ( "my_port" . to_string ( ) ) ,
1342
+ } ;
1343
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1344
+ let res: ListChannelsResponse = from_binary ( & raw ) . unwrap ( ) ;
1345
+ assert_eq ! ( res. channels, vec![ chan1, chan2] ) ;
1346
+ }
1347
+
1348
+ #[ cfg( feature = "stargate" ) ]
1349
+ #[ test]
1350
+ fn ibc_querier_channels_no_matching ( ) {
1351
+ let chan1 = mock_ibc_channel ( "channel-0" , IbcOrder :: Ordered , "ibc" ) ;
1352
+ let chan2 = mock_ibc_channel ( "channel-1" , IbcOrder :: Ordered , "ibc" ) ;
1353
+
1354
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1, chan2] ) ;
1355
+
1356
+ // query channels matching "myport" (should be none)
1357
+ let query = & & IbcQuery :: ListChannels { port_id : None } ;
1358
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1359
+ let res: ListChannelsResponse = from_binary ( & raw ) . unwrap ( ) ;
1360
+ assert_eq ! ( res. channels, vec![ ] ) ;
1361
+ }
1362
+
1363
+ #[ cfg( feature = "stargate" ) ]
1364
+ #[ test]
1365
+ fn ibc_querier_port ( ) {
1366
+ let chan1 = mock_ibc_channel ( "channel-0" , IbcOrder :: Ordered , "ibc" ) ;
1367
+
1368
+ let ibc = IbcQuerier :: new ( "myport" , & [ chan1] ) ;
1369
+
1370
+ // query channels matching "myport" (should be none)
1371
+ let query = & & IbcQuery :: PortId { } ;
1372
+ let raw = ibc. query ( query) . unwrap ( ) . unwrap ( ) ;
1373
+ let res: PortIdResponse = from_binary ( & raw ) . unwrap ( ) ;
1374
+ assert_eq ! ( res. port_id, "myport" ) ;
1375
+ }
1376
+
1192
1377
#[ cfg( feature = "staking" ) ]
1193
1378
#[ test]
1194
1379
fn staking_querier_all_validators ( ) {
0 commit comments