polytone_evm/
accounts.rs

1use cosmwasm_std::{Addr, StdResult, Storage};
2use cw_storage_plus::Map;
3
4/// (channel_id, sequence_number) -> sender
5///
6/// Maps packets to the address that sent them.
7const PENDING: Map<(String, u64), Addr> = Map::new("polytone-accounts-pending");
8
9/// (local_account) -> remote_account
10///
11/// Maps local addresses to their remote counterparts.
12const LOCAL_TO_REMOTE_ACCOUNT: Map<Addr, String> = Map::new("polytone-account-map");
13
14pub fn on_send_packet(
15    storage: &mut dyn Storage,
16    channel_id: String,
17    sequence_number: u64,
18    sender: &Addr,
19) -> StdResult<()> {
20    PENDING.save(storage, (channel_id, sequence_number), sender)
21}
22
23pub fn on_ack(
24    storage: &mut dyn Storage,
25    channel_id: String,
26    sequence_number: u64,
27    executor: Option<String>,
28) {
29    let local_account = PENDING
30        .load(storage, (channel_id.clone(), sequence_number))
31        .expect("pending was set when sending packet");
32
33    PENDING.remove(storage, (channel_id, sequence_number));
34
35    if let Some(executor) = executor {
36        LOCAL_TO_REMOTE_ACCOUNT
37            .save(storage, local_account, &executor)
38            .expect("strings were loaded from storage, so should serialize");
39    }
40}
41
42pub fn on_timeout(storage: &mut dyn Storage, channel_id: String, sequence_number: u64) {
43    PENDING.remove(storage, (channel_id, sequence_number))
44}
45
46pub fn query_account(storage: &dyn Storage, local_address: Addr) -> StdResult<Option<String>> {
47    LOCAL_TO_REMOTE_ACCOUNT.may_load(storage, local_address)
48}
49
50#[cfg(test)]
51mod tests {
52    use cosmwasm_std::testing::mock_dependencies;
53
54    use super::*;
55
56    /// In the event of channel closure, this package will see the
57    /// channel ID in packets change. Tests that state is kept
58    /// correctly in this event.
59    #[test]
60    fn test_channel_closure() {
61        let mut deps = mock_dependencies();
62        let storage = deps.as_mut().storage;
63
64        let channel_id = "channel-0".to_string();
65        let sender = Addr::unchecked("sender");
66
67        // send first packet to create account on remote chain.
68        on_send_packet(storage, channel_id.clone(), 1, &sender).unwrap();
69        on_ack(storage, channel_id, 1, Some("remote".to_string()));
70
71        let remote_account = query_account(storage, sender.clone());
72
73        let channel_id = "channel-1".to_string();
74
75        // send first packet to create account on remote chain.
76        on_send_packet(storage, channel_id.clone(), 1, &sender).unwrap();
77        on_ack(storage, channel_id, 1, Some("remote".to_string()));
78
79        let new_remote_account = query_account(storage, sender);
80        assert_eq!(
81            new_remote_account, remote_account,
82            "changing the channel shouldn't change the account"
83        )
84    }
85}