1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use core::str::{from_utf8, FromStr, Utf8Error};
use std::num::ParseIntError;

use cgp::core::error::CanRaiseError;
use hermes_cosmos_chain_components::types::event::AbciEvent;
use hermes_relayer_components::chain::traits::send_message::CanSendSingleMessage;
use hermes_test_components::chain::traits::proposal::types::proposal_id::HasProposalIdType;

use crate::traits::chain::messages::store_code::CanBuildStoreCodeMessage;
use crate::traits::chain::upload_client_code::WasmClientCodeUploader;

pub struct SendStoreCodeProposalMessage;

#[derive(Debug)]
pub struct ProposalIdNotFound;

impl<Chain> WasmClientCodeUploader<Chain> for SendStoreCodeProposalMessage
where
    Chain: CanBuildStoreCodeMessage
        + CanSendSingleMessage
        + HasProposalIdType<ProposalId = u64>
        + CanRaiseError<Utf8Error>
        + CanRaiseError<ParseIntError>
        + CanRaiseError<ProposalIdNotFound>,
    Chain::Event: AsRef<AbciEvent>,
{
    async fn upload_wasm_client_code(
        chain: &Chain,
        wasm_client_bytes: &Vec<u8>,
        title: &str,
        summary: &str,
        authority: &Chain::Address,
        deposit_amount: &Chain::Amount,
    ) -> Result<u64, Chain::Error> {
        let message = chain.build_store_code_message(
            wasm_client_bytes,
            title,
            summary,
            authority,
            deposit_amount,
        );

        let events = chain.send_message(message).await?;

        for event in events {
            if event.as_ref().kind == "submit_proposal" {
                for attribute in event.as_ref().attributes.iter() {
                    if attribute.key_bytes() == "proposal_id".as_bytes() {
                        let proposal_id_str =
                            from_utf8(attribute.value_bytes()).map_err(Chain::raise_error)?;

                        let proposal_id =
                            u64::from_str(proposal_id_str).map_err(Chain::raise_error)?;

                        return Ok(proposal_id);
                    }
                }
            }
        }

        Err(Chain::raise_error(ProposalIdNotFound))
    }
}