CosmWasm / sylvia

CosmWasm smart contract framework
Apache License 2.0
88 stars 14 forks source link

Add impl From<VARIANTS> for Contract{Exec,Query,Sudo}Msg #376

Closed ethanfrey closed 6 days ago

ethanfrey commented 2 months ago

This is needed for full cw-orch codegen support #374 but is actually independent of cw-orch and could be a useful helper in any case. In order to explain what I request, I will use the cw20_base contract from the sylvia repo as an example. If we look at cw20_base::contract::sv::ContractExecMsg, the codegen is:

pub enum ContractExecMsg {
    Allowances(<cw20_allowances::sv::Api as InterfaceApi>::Exec),
    Marketing(<cw20_marketing::sv::Api as InterfaceApi>::Exec),
    Minting(<cw20_minting::sv::Api as InterfaceApi>::Exec),
    Cw20Base(ExecMsg),
}

Thanks to the regular generation of Sylvia code, this is always equivalent to:

pub enum ContractExecMsg {
    Allowances(cw20_allowances::sv::Cw20AllowancesExecMsg),
    Marketing(cw20_marketing::sv::Cw20MarketingExecMsg),
    Minting(cw20_minting::sv::Cw20MintingExecMsg),
    Cw20Base(ExecMsg),
}

You cannot implement the from on those associated types without the compiler yelling at you about conflicting From implementations. So the second version is much easier to work with. Given that, I would like Sylvia to generate the following implementations:

impl From<cw20_allowances::sv::Cw20AllowancesExecMsg> for ContractExecMsg {
    fn from(msg: cw20_allowances::sv::Cw20AllowancesExecMsg) -> Self {
        ContractExecMsg::Allowances(msg)
    }
}

impl From<cw20_marketing::sv::Cw20MarketingExecMsg> for ContractExecMsg {
    fn from(msg: cw20_marketing::sv::Cw20MarketingExecMsg) -> Self {
        ContractExecMsg::Marketing(msg)
    }
}

impl From<cw20_minting::sv::Cw20MintingExecMsg> for ContractExecMsg {
    fn from(msg: cw20_minting::sv::Cw20MintingExecMsg) -> Self {
        ContractExecMsg::Minting(msg)
    }
}

impl From<ExecMsg> for ContractExecMsg {
    fn from(msg: ExecMsg) -> Self {
        ContractExecMsg::Cw20Base(msg)
    }
}

And of course the same for *QueryMsg and *SudoMsg as well. This will allow easier programmatic usage of the concrete dispatched types for those "going under the hood" of Sylvia a bit. Again, cw-orch has this concrete need, but I don't see the issue of adding this code in general, not under any feature flag. An implementation to generate the last item could be found in #375. Generating the From for the interface messages was harder and lead to the stack overflow issue.

Note: Requested for the cosmwasm-1.x branch (and ported to / backported from main)

Pinging @jawoznia for your thoughts here

hashedone commented 2 months ago

Those impls could be there, but we do not generate them as eventually, those messages should never need to be created directly, the user should create them with #130. However, executors are not yet implemented, and I believe this would be an easy addition and not harm us in any way. Added to 1.1.0 milestone.

kulikthebird commented 2 weeks ago

Main reason for this task was to simplify generating exec messages for Sylvia contracts. The task https://github.com/CosmWasm/sylvia/issues/130 is finished, so do we still have any use case for this issue?

Now instead of this:

let msg = cw20_base::contract::ContractExecMsg::Minting(cw20_minting::sv::Cw20MintingExecMsg::Mint {
        recipient: mock.sender.to_string(),
        amount: 150_000u128.into(),
});

We can build the already serialized WasmMsg containing the exec message like this:

use cosmwasm_std::WasmMsg
use cw20_base::contract::ContractExecMsg;
use cw20_minting::sv::Executor;
use sylvia::types::Remote;

let remote: Remote<ContractExecMsg> = Remote::new("contract_address");
let msg: WasmMsg =
    remote.executor()
        .with_funds(vec![coin(2345, "atom")])
        .mint(mock.sender.to_string(), 150_000u128.into())?
        .build();
kulikthebird commented 1 week ago

Since the issue is still valid, it will be solved in #391, merged to main and released in sylvia v1.1.0.