2
2
use cosmwasm_std:: entry_point;
3
3
4
4
use cosmwasm_std:: {
5
- from_slice, DepsMut , Env , Ibc3ChannelOpenResponse , IbcBasicResponse , IbcChannel ,
6
- IbcChannelCloseMsg , IbcChannelConnectMsg , IbcChannelOpenMsg , IbcChannelOpenResponse ,
5
+ from_slice, to_binary , DepsMut , Env , Ibc3ChannelOpenResponse , IbcBasicResponse , IbcChannel ,
6
+ IbcChannelCloseMsg , IbcChannelConnectMsg , IbcChannelOpenMsg , IbcChannelOpenResponse , IbcMsg ,
7
7
IbcPacketAckMsg , IbcPacketReceiveMsg , IbcPacketTimeoutMsg , IbcReceiveResponse , IbcTimeout ,
8
+ Timestamp ,
8
9
} ;
9
10
use cw_storage_plus:: Item ;
10
- use mesh_apis:: ibc:: { validate_channel_order, PriceFeedProviderPacket , ProtocolVersion } ;
11
+ use mesh_apis:: ibc:: {
12
+ validate_channel_order, PriceFeedProviderAck , ProtocolVersion , RemotePriceFeedPacket ,
13
+ } ;
11
14
12
15
use crate :: contract:: RemotePriceFeedContract ;
13
16
use crate :: error:: ContractError ;
14
17
use crate :: msg:: AuthorizedEndpoint ;
18
+ use crate :: state:: PriceInfo ;
15
19
16
20
/// This is the maximum version of the Mesh Security protocol that we support
17
21
const SUPPORTED_IBC_PROTOCOL_VERSION : & str = "0.11.0" ;
@@ -20,16 +24,11 @@ const MIN_IBC_PROTOCOL_VERSION: &str = "0.11.0";
20
24
21
25
// IBC specific state
22
26
pub const AUTH_ENDPOINT : Item < AuthorizedEndpoint > = Item :: new ( "auth_endpoint" ) ;
23
- pub const IBC_CHANNEL : Item < IbcChannel > = Item :: new ( "ibc_channel" ) ;
24
27
25
- // If we don't hear anything within 10 minutes, let's abort, for better UX
26
- // This is long enough to allow some clock drift between chains
27
- const DEFAULT_TIMEOUT : u64 = 10 * 60 ;
28
+ const TIMEOUT : u64 = 10 * 60 ;
28
29
29
- pub fn packet_timeout ( env : & Env ) -> IbcTimeout {
30
- // No idea about their block time, but 24 hours ahead of our view of the clock
31
- // should be decently in the future.
32
- let timeout = env. block . time . plus_seconds ( DEFAULT_TIMEOUT ) ;
30
+ pub fn packet_timeout ( now : & Timestamp ) -> IbcTimeout {
31
+ let timeout = now. plus_seconds ( TIMEOUT ) ;
33
32
IbcTimeout :: with_timestamp ( timeout)
34
33
}
35
34
@@ -41,7 +40,8 @@ pub fn ibc_channel_open(
41
40
msg : IbcChannelOpenMsg ,
42
41
) -> Result < IbcChannelOpenResponse , ContractError > {
43
42
// ensure we have no channel yet
44
- if IBC_CHANNEL . may_load ( deps. storage ) ?. is_some ( ) {
43
+ let contract = RemotePriceFeedContract :: new ( ) ;
44
+ if contract. channel . may_load ( deps. storage ) ?. is_some ( ) {
45
45
return Err ( ContractError :: IbcChannelAlreadyOpen ) ;
46
46
}
47
47
// ensure we are called with OpenInit
@@ -83,8 +83,10 @@ pub fn ibc_channel_connect(
83
83
_env : Env ,
84
84
msg : IbcChannelConnectMsg ,
85
85
) -> Result < IbcBasicResponse , ContractError > {
86
+ let contract = RemotePriceFeedContract :: new ( ) ;
87
+
86
88
// ensure we have no channel yet
87
- if IBC_CHANNEL . may_load ( deps. storage ) ?. is_some ( ) {
89
+ if contract . channel . may_load ( deps. storage ) ?. is_some ( ) {
88
90
return Err ( ContractError :: IbcChannelAlreadyOpen ) ;
89
91
}
90
92
// ensure we are called with OpenConfirm
@@ -94,7 +96,8 @@ pub fn ibc_channel_connect(
94
96
} ;
95
97
96
98
// Version negotiation over, we can only store the channel
97
- IBC_CHANNEL . save ( deps. storage , & channel) ?;
99
+ let contract = RemotePriceFeedContract :: new ( ) ;
100
+ contract. channel . save ( deps. storage , & channel) ?;
98
101
99
102
Ok ( IbcBasicResponse :: default ( ) )
100
103
}
@@ -110,29 +113,30 @@ pub fn ibc_channel_close(
110
113
111
114
#[ cfg_attr( not( feature = "library" ) , entry_point) ]
112
115
pub fn ibc_packet_receive (
113
- deps : DepsMut ,
116
+ _deps : DepsMut ,
114
117
_env : Env ,
115
- msg : IbcPacketReceiveMsg ,
118
+ _msg : IbcPacketReceiveMsg ,
116
119
) -> Result < IbcReceiveResponse , ContractError > {
117
- let packet: PriceFeedProviderPacket = from_slice ( & msg. packet . data ) ?;
118
- let resp = match packet {
119
- PriceFeedProviderPacket :: Update { twap } => {
120
- let contract = RemotePriceFeedContract :: new ( ) ;
121
- contract. native_per_foreign . save ( deps. storage , & twap) ?;
122
- IbcReceiveResponse :: new ( )
123
- }
124
- } ;
125
-
126
- Ok ( resp)
120
+ Err ( ContractError :: IbcReceiveNotAccepted )
127
121
}
128
122
129
123
#[ cfg_attr( not( feature = "library" ) , entry_point) ]
130
124
pub fn ibc_packet_ack (
131
- _deps : DepsMut ,
125
+ deps : DepsMut ,
132
126
_env : Env ,
133
- _msg : IbcPacketAckMsg ,
127
+ msg : IbcPacketAckMsg ,
134
128
) -> Result < IbcBasicResponse , ContractError > {
135
- Err ( ContractError :: IbcAckNotAccepted )
129
+ let ack: PriceFeedProviderAck = from_slice ( & msg. acknowledgement . data ) ?;
130
+ let PriceFeedProviderAck :: Update { twap } = ack;
131
+ let contract = RemotePriceFeedContract :: new ( ) ;
132
+ contract. price_info . save (
133
+ deps. storage ,
134
+ & PriceInfo {
135
+ native_per_foreign : twap,
136
+ } ,
137
+ ) ?;
138
+
139
+ Ok ( IbcBasicResponse :: new ( ) )
136
140
}
137
141
138
142
#[ cfg_attr( not( feature = "library" ) , entry_point) ]
@@ -141,5 +145,17 @@ pub fn ibc_packet_timeout(
141
145
_env : Env ,
142
146
_msg : IbcPacketTimeoutMsg ,
143
147
) -> Result < IbcBasicResponse , ContractError > {
144
- Err ( ContractError :: IbcAckNotAccepted )
148
+ Err ( ContractError :: IbcReceiveNotAccepted )
149
+ }
150
+
151
+ pub ( crate ) fn make_ibc_packet (
152
+ now : & Timestamp ,
153
+ channel : IbcChannel ,
154
+ packet : RemotePriceFeedPacket ,
155
+ ) -> Result < IbcMsg , ContractError > {
156
+ Ok ( IbcMsg :: SendPacket {
157
+ channel_id : channel. endpoint . channel_id ,
158
+ data : to_binary ( & packet) ?,
159
+ timeout : packet_timeout ( now) ,
160
+ } )
145
161
}
0 commit comments