Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added instantiate2 #309

Merged
merged 9 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions cw-orch-daemon/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@

use cosmrs::{
cosmwasm::{MsgExecuteContract, MsgInstantiateContract, MsgMigrateContract},
proto::cosmwasm::wasm::v1::MsgInstantiateContract2,
tendermint::Time,
AccountId, Denom,
AccountId, Any, Denom,
};
use cosmwasm_std::{Addr, Coin};
use cosmwasm_std::{Addr, Binary, Coin};
use cw_orch_core::{
contract::interface_traits::Uploadable,
environment::{ChainState, IndexResponse},
log::transaction_target,
};
use flate2::{write, Compression};
use prost::Message;
use serde::{de::DeserializeOwned, Serialize};
use serde_json::from_str;
use std::{
Expand Down Expand Up @@ -162,6 +164,44 @@
Ok(result)
}

/// Instantiate a contract.
pub async fn instantiate2<I: Serialize + Debug>(
&self,
code_id: u64,
init_msg: &I,
label: Option<&str>,
admin: Option<&Addr>,
coins: &[Coin],
salt: Binary,
) -> Result<CosmTxResponse, DaemonError> {
let sender = &self.sender;

let init_msg = MsgInstantiateContract2 {
code_id,
label: label.unwrap_or("instantiate_contract").to_string(),
admin: admin.map(Into::into).unwrap_or_default(),
sender: sender.address()?.to_string(),
msg: serde_json::to_vec(&init_msg)?,
funds: proto_parse_cw_coins(coins)?,
salt: salt.to_vec(),
fix_msg: false,
Buckram123 marked this conversation as resolved.
Show resolved Hide resolved
};

let result = sender
.commit_tx_any(
vec![Any {
type_url: "/cosmwasm.wasm.v1.MsgInstantiateContract2".to_string(),
Buckram123 marked this conversation as resolved.
Show resolved Hide resolved
value: init_msg.encode_to_vec(),
}],
None,
)
.await?;

log::info!(target: &transaction_target(), "Instantiation done: {:?}", result.txhash);

Ok(result)
}

/// Query a contract.
pub async fn query<Q: Serialize + Debug, T: Serialize + DeserializeOwned>(
&self,
Expand Down Expand Up @@ -299,3 +339,17 @@
})
.collect::<Result<Vec<_>, DaemonError>>()
}

pub(crate) fn proto_parse_cw_coins(
coins: &[cosmwasm_std::Coin],
) -> Result<Vec<cosmrs::proto::cosmos::base::v1beta1::Coin>, DaemonError> {
coins
.iter()
.map(|cosmwasm_std::Coin { amount, denom }| {
Ok(cosmrs::proto::cosmos::base::v1beta1::Coin {
amount: amount.to_string(),
denom: denom.clone(),
})

Check warning on line 352 in cw-orch-daemon/src/core.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch-daemon/src/core.rs#L349-L352

Added lines #L349 - L352 were not covered by tests
})
.collect::<Result<Vec<_>, DaemonError>>()
}
4 changes: 3 additions & 1 deletion cw-orch-daemon/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(missing_docs)]

use cosmwasm_std::Coin;
use cosmwasm_std::{Coin, Instantiate2AddressError};
use cw_orch_core::CwEnvError;
use thiserror::Error;

Expand Down Expand Up @@ -118,6 +118,8 @@ pub enum DaemonError {
NotEnoughBalance { expected: Coin, current: Coin },
#[error("Can't set the daemon state, it's read-only")]
StateReadOnly,
#[error(transparent)]
Instantiate2Error(#[from] Instantiate2AddressError),
}

impl DaemonError {
Expand Down
27 changes: 24 additions & 3 deletions cw-orch-daemon/src/queriers/cosmwasm.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use std::str::FromStr;

use super::DaemonQuerier;
use crate::{cosmos_modules, error::DaemonError, Daemon};
use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest;
use cosmwasm_std::{from_json, to_json_binary, CodeInfoResponse, ContractInfoResponse};
use cosmrs::AccountId;
use cosmwasm_std::{
from_json, instantiate2_address, to_json_binary, CanonicalAddr, CodeInfoResponse,
ContractInfoResponse,
};
use cw_orch_core::environment::{Querier, QuerierGetter, WasmQuerier};
use tokio::runtime::Handle;
use tonic::transport::Channel;

use super::DaemonQuerier;

/// Querier for the CosmWasm SDK module
pub struct CosmWasm {
channel: Channel,
Expand Down Expand Up @@ -265,4 +270,20 @@

Ok(c)
}

fn instantiate2_addr<I: serde::Serialize + std::fmt::Debug>(
&self,
code_id: u64,
creator: impl Into<String>,
salt: cosmwasm_std::Binary,
) -> Result<String, Self::Error> {
let creator_str = creator.into();
let account_id = AccountId::from_str(&creator_str)?;
let prefix = account_id.prefix();
let canon = account_id.to_bytes();
let checksum = self.code_id_hash(code_id)?;
let addr = instantiate2_address(checksum.as_bytes(), &CanonicalAddr(canon.into()), &salt)?;

Check warning on line 285 in cw-orch-daemon/src/queriers/cosmwasm.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch-daemon/src/queriers/cosmwasm.rs#L274-L285

Added lines #L274 - L285 were not covered by tests

Ok(AccountId::new(prefix, &addr.0)?.to_string())
}

Check warning on line 288 in cw-orch-daemon/src/queriers/cosmwasm.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch-daemon/src/queriers/cosmwasm.rs#L287-L288

Added lines #L287 - L288 were not covered by tests
}
15 changes: 15 additions & 0 deletions cw-orch-daemon/src/sync/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ impl TxHandler for Daemon {
.migrate(migrate_msg, new_code_id, contract_address),
)
}

fn instantiate2<I: Serialize + Debug>(
&self,
code_id: u64,
init_msg: &I,
label: Option<&str>,
admin: Option<&Addr>,
coins: &[cosmwasm_std::Coin],
salt: cosmwasm_std::Binary,
) -> Result<Self::Response, Self::Error> {
self.rt_handle.block_on(
self.daemon
.instantiate2(code_id, init_msg, label, admin, coins, salt),
)
}
}

impl Stargate for Daemon {
Expand Down
36 changes: 36 additions & 0 deletions cw-orch-daemon/tests/instantiate2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
mod common;

#[cfg(feature = "node-tests")]
pub mod test {

use cosmwasm_std::Binary;
use cw_orch_core::contract::interface_traits::ContractInstance;
use cw_orch_core::contract::interface_traits::CwOrchInstantiate;
use cw_orch_core::contract::interface_traits::CwOrchUpload;
use cw_orch_daemon::Daemon;
use cw_orch_networks::networks;
use mock_contract::InstantiateMsg;
use mock_contract::MockContract;

#[test]
fn instantiate2() -> anyhow::Result<()> {
let runtime = tokio::runtime::Runtime::new().unwrap();

let app = Daemon::builder()
.chain(networks::LOCAL_JUNO)
.handle(runtime.handle())
.build()
.unwrap();

let salt = Binary(vec![12, 89, 156, 63]);
let mock_contract = MockContract::new("mock-contract", app.clone());

mock_contract.upload()?;

mock_contract.instantiate2(&InstantiateMsg {}, None, None, salt.clone())?;

mock_contract.address()?;

Ok(())
}
}
12 changes: 12 additions & 0 deletions cw-orch/src/osmosis_test_tube/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,18 @@
) -> Result<Self::Response, CwOrchError> {
panic!("Migrate not implemented on osmosis test_tube")
}

fn instantiate2<I: Serialize + Debug>(
&self,
_code_id: u64,
_init_msg: &I,
_label: Option<&str>,
_admin: Option<&Addr>,
_coins: &[cosmwasm_std::Coin],
_salt: Binary,
) -> Result<Self::Response, Self::Error> {
unimplemented!("Osmosis Test Tube doesn't support Instantiate 2 directly");

Check warning on line 280 in cw-orch/src/osmosis_test_tube/core.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch/src/osmosis_test_tube/core.rs#L271-L280

Added lines #L271 - L280 were not covered by tests
}
}

impl BankSetter for OsmosisTestTube {
Expand Down
26 changes: 24 additions & 2 deletions cw-orch/src/osmosis_test_tube/queriers/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::{cell::RefCell, rc::Rc};
use std::{cell::RefCell, rc::Rc, str::FromStr};

use cosmwasm_std::{from_json, to_json_vec, CodeInfoResponse, ContractInfoResponse};
use cosmrs::AccountId;
use cosmwasm_std::{
from_json, instantiate2_address, to_json_vec, CanonicalAddr, CodeInfoResponse,
ContractInfoResponse,
};
use cw_orch_core::{
environment::{Querier, QuerierGetter, StateInterface, WasmQuerier},
CwEnvError,
Expand Down Expand Up @@ -152,4 +156,22 @@

Ok(c)
}

fn instantiate2_addr<I: serde::Serialize + std::fmt::Debug>(
&self,
code_id: u64,
creator: impl Into<String>,
salt: cosmwasm_std::Binary,
) -> Result<String, Self::Error> {
let checksum = self.code_id_hash(code_id)?;

Check warning on line 166 in cw-orch/src/osmosis_test_tube/queriers/wasm.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch/src/osmosis_test_tube/queriers/wasm.rs#L160-L166

Added lines #L160 - L166 were not covered by tests

let creator_str = creator.into();
let account_id = AccountId::from_str(&creator_str).unwrap();
let prefix = account_id.prefix();
let canon = account_id.to_bytes();
let addr =
instantiate2_address(checksum.as_bytes(), &CanonicalAddr(canon.into()), &salt).unwrap();

Ok(AccountId::new(prefix, &addr.0).unwrap().to_string())
}

Check warning on line 176 in cw-orch/src/osmosis_test_tube/queriers/wasm.rs

View check run for this annotation

Codecov / codecov/patch

cw-orch/src/osmosis_test_tube/queriers/wasm.rs#L168-L176

Added lines #L168 - L176 were not covered by tests
}
54 changes: 53 additions & 1 deletion packages/cw-orch-core/src/contract/contract_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
};

use crate::environment::QueryHandler;
use cosmwasm_std::{Addr, Coin};
use cosmwasm_std::{Addr, Binary, Coin};
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;

Expand Down Expand Up @@ -171,6 +171,58 @@ impl<Chain: TxHandler + QueryHandler + Clone> Contract<Chain> {
Ok(resp)
}

/// Initializes the contract
pub fn instantiate2<I: Serialize + Debug>(
&self,
msg: &I,
admin: Option<&Addr>,
coins: Option<&[Coin]>,
salt: Binary,
) -> Result<TxResponse<Chain>, CwEnvError> {
log::info!(
target: &contract_target(),
"[{}][Instantiate]",
self.id,
);

log::debug!(
target: &contract_target(),
"[{}][Instantiate] {}",
self.id,
log_serialize_message(msg)?
);

let resp = self
.chain
.instantiate2(
self.code_id()?,
msg,
Some(&self.id),
admin,
coins.unwrap_or(&[]),
salt,
)
.map_err(Into::into)?;
let contract_address = resp.instantiated_contract_address()?;

self.set_address(&contract_address);

log::info!(
target: &&contract_target(),
"[{}][Instantiated] {}",
self.id,
contract_address
);
log::debug!(
target: &&transaction_target(),
"[{}][Instantiated] response: {:?}",
self.id,
resp
);

Ok(resp)
}

/// Query the contract
pub fn query<Q: Serialize + Debug, T: Serialize + DeserializeOwned + Debug>(
&self,
Expand Down
14 changes: 13 additions & 1 deletion packages/cw-orch-core/src/contract/interface_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
error::CwEnvError,
log::contract_target,
};
use cosmwasm_std::{Addr, Coin, Empty};
use cosmwasm_std::{Addr, Binary, Coin, Empty};
use cw_multi_test::Contract as MockContract;
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;
Expand Down Expand Up @@ -118,6 +118,18 @@ pub trait CwOrchInstantiate<Chain: CwEnv>: InstantiableContract + ContractInstan
self.as_instance()
.instantiate(instantiate_msg, admin, coins)
}

/// Instantiates the contract using instantiate2
fn instantiate2(
&self,
instantiate_msg: &Self::InstantiateMsg,
admin: Option<&Addr>,
coins: Option<&[Coin]>,
salt: Binary,
) -> Result<Chain::Response, CwEnvError> {
self.as_instance()
.instantiate2(instantiate_msg, admin, coins, salt)
}
}

impl<T: InstantiableContract + ContractInstance<Chain>, Chain: CwEnv> CwOrchInstantiate<Chain>
Expand Down
25 changes: 24 additions & 1 deletion packages/cw-orch-core/src/environment/cosmwasm_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{queriers::QueryHandler, ChainState, IndexResponse};
use crate::{contract::interface_traits::Uploadable, error::CwEnvError};
use cosmwasm_std::{Addr, Coin};
use cosmwasm_std::{Addr, Binary, Coin};
use serde::Serialize;
use std::fmt::Debug;

Expand Down Expand Up @@ -46,6 +46,17 @@
coins: &[cosmwasm_std::Coin],
) -> Result<Self::Response, Self::Error>;

/// Send a Instantiate2Msg to a contract.
fn instantiate2<I: Serialize + Debug>(
&self,
code_id: u64,
init_msg: &I,
label: Option<&str>,
admin: Option<&Addr>,
coins: &[cosmwasm_std::Coin],
salt: Binary,
) -> Result<Self::Response, Self::Error>;

Comment on lines +49 to +59
Copy link
Contributor

@Buckram123 Buckram123 Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to return (yet) not executed instantiate2 struct instead? Main use for instantiate2 will be knowing the address, before instantiating. I'm expecting experience to be something like:

let contract1 = chain.instantiate2(...)?;
let contract1_addr = contract1.addr()?;
let contract2 = chain.instantiate2(...)?;
let contract2_addr = contract2.addr()?;
// ...
contract1.submit(Contract1InstantiateMsg{
    contract2_addr: contract2_addr.to_string()
})?;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what you mean here ? You want a function that would return the instantiate2 addr if ever it was instantiated ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what you mean here ? You want a function that would return the instantiate2 addr if ever it was instantiated ?

Yes, I want function that can return the address of pre-filled, but not executed instantiate2 message.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using helpers such as https://docs.rs/cosmwasm-std/latest/cosmwasm_std/fn.instantiate2_address.html would be annoying, so I would prefer it to be as a part of API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK,implemented what we discussed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is now a method on the wasm querier correct?

/// Send a ExecMsg to a contract.
fn execute<E: Serialize + Debug>(
&self,
Expand Down Expand Up @@ -169,6 +180,18 @@
) -> Result<Self::Response, Self::Error> {
unimplemented!()
}

fn instantiate2<I: Serialize + Debug>(
&self,
_code_id: u64,
_init_msg: &I,
_label: Option<&str>,
_admin: Option<&Addr>,
_coins: &[cosmwasm_std::Coin],
_salt: Binary,
) -> Result<Self::Response, Self::Error> {
unimplemented!()
}

Check warning on line 194 in packages/cw-orch-core/src/environment/cosmwasm_environment.rs

View check run for this annotation

Codecov / codecov/patch

packages/cw-orch-core/src/environment/cosmwasm_environment.rs#L184-L194

Added lines #L184 - L194 were not covered by tests
}

fn associated_error<T: TxHandler>(t: T) -> anyhow::Result<()> {
Expand Down
Loading
Loading