Skip to content

Commit

Permalink
Merge pull request #13 from timewave-computer/dowlandaiello/enhanceme…
Browse files Browse the repository at this point in the history
…nt-instantiate2

Implement Instantiate2
  • Loading branch information
dowlandaiello authored Aug 17, 2024
2 parents 315128e + 543f6b5 commit 6738206
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 99 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ sha2 = "0.10.8"

[dev-dependencies]
env_logger = "0.11.3"
hex = "0.4.3"
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,24 @@ Note that most `tx_*` helper functions expose a `.with_key(key: &str)` builder f
* No required builder calls
* No notable optional builder calls

#### Wasm

* `.build_tx_instantiate2` - Predictably instantiates a CosmWasm contract.
* Required builder calls:
* `.with_code_id(code_id: u64)` - Should be the raw code ID of the contract being instantiated
* `.with_salt_hex_encoded(salt: &str)` - Should be a **hex-encoded** salt for instantiation
* `.with_msg(msg: serde_json::Value)`
* `.with_label(label: &str)`
* Notable optional builder calls:
* `.with_chain_name(chain_name: impl Into<String>)` - Should be one of `"osmosis" | "neutron"` or one of the registered chain names from `.with_chain`

#### Tokens

* `.build_tx_create_tokenfactory_token` - Creates a tokenfactory token from `acc0` on Neutron by default.
* Required builder calls:
* `.with_subdenom(subdenom: &str)`
* Notable optional builder calls:
* `.with_chain_name(chain_name: impl Into<String>)` - Should be on of `"osmosis" | "neutron" | "stride"` or one of the registered chain names from `.with_chain`
* `.with_chain_name(chain_name: impl Into<String>)` - Should be one of `"osmosis" | "neutron" | "stride"` or one of the registered chain names from `.with_chain`
* `.get_tokenfactory_denom(key: &str, subdenom: &str)` - Gets the tokenfactory denom of a tokenfactory token given its subdenom and key
* `.build_tx_mint_tokenfactory_token` - Mints a tokenfactory token from `acc0` on Neutron by default.
* Required builder calls
Expand Down
39 changes: 38 additions & 1 deletion examples/neutron.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use cosmwasm_std::Decimal;
use localic_utils::{types::contract::MinAmount, ConfigChainBuilder, TestContextBuilder};
use localic_utils::{
types::contract::MinAmount, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY,
};
use std::error::Error;

const ACC_0_ADDR: &str = "neutron1hj5fveer5cjtn4wd6wstzugjfdxzl0xpznmsky";
Expand Down Expand Up @@ -124,5 +126,40 @@ fn main() -> Result<(), Box<dyn Error>> {
.with_liq_token_receiver(ACC_0_ADDR)
.send()?;

let factory_contract_code_id = ctx
.get_contract("astroport_whitelist")
.unwrap()
.code_id
.unwrap();

// Instantiate a contract with a predictable address
ctx.build_tx_instantiate2()
.with_code_id(factory_contract_code_id)
.with_msg(serde_json::json!({
"admins": [],
"mutable": false,
}))
.with_salt_hex_encoded(hex::encode("examplesalt").as_str())
.with_label("test_contract")
.send()
.unwrap();

let addr = ctx
.get_built_contract_address()
.contract("astroport_whitelist")
.creator(ACC_0_ADDR)
.salt_hex_encoded(hex::encode("examplesalt").as_str())
.get();

let mut cw = ctx.get_contract("astroport_whitelist").unwrap();
cw.contract_addr = Some(addr);

cw.execute(
DEFAULT_KEY,
&serde_json::json!({ "execute": { "msgs": [] } }).to_string(),
"",
)
.unwrap();

Ok(())
}
2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod fixtures;
pub mod fs;
pub mod queries;
pub mod setup;
pub mod test_context;
File renamed without changes.
1 change: 1 addition & 0 deletions src/utils/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod osmosis;
pub mod stride;
pub mod tokens;
pub mod valence;
pub mod wasm;
152 changes: 152 additions & 0 deletions src/utils/setup/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
use super::super::{
super::{error::Error, DEFAULT_KEY, NEUTRON_CHAIN_NAME},
test_context::TestContext,
};
use cosmwasm_std::Coin;
use serde_json::Value;

pub struct Instantiate2TxBuilder<'a> {
key: &'a str,
chain_name: &'a str,
admin: Option<&'a str>,
code_id: Option<u64>,
label: Option<&'a str>,
msg: Option<Value>,
funds: Option<Coin>,

// Not automatically hex-encoded.
// Assume the user performs hex encoding
salt: Option<&'a str>,
fix_msg: Option<bool>,
test_ctx: &'a mut TestContext,
}

impl<'a> Instantiate2TxBuilder<'a> {
pub fn with_key(&mut self, key: &'a str) -> &mut Self {
self.key = key;

self
}

pub fn with_chain_name(&mut self, chain_name: &'a str) -> &mut Self {
self.chain_name = chain_name;

self
}

pub fn with_admin(&mut self, admin: &'a str) -> &mut Self {
self.admin = Some(admin);

self
}

pub fn with_code_id(&mut self, code_id: u64) -> &mut Self {
self.code_id = Some(code_id);

self
}

pub fn with_label(&mut self, label: &'a str) -> &mut Self {
self.label = Some(label);

self
}

pub fn with_msg(&mut self, msg: Value) -> &mut Self {
self.msg = Some(msg);

self
}

pub fn with_funds(&mut self, funds: Coin) -> &mut Self {
self.funds = Some(funds);

self
}

/// Sets the salt. Value must be hex encoded.
pub fn with_salt_hex_encoded(&mut self, salt: &'a str) -> &mut Self {
self.salt = Some(salt);

self
}

pub fn with_fix_msg(&mut self, fix_msg: bool) -> &mut Self {
self.fix_msg = Some(fix_msg);

self
}

/// Sends the built instantiate 2 tx.
pub fn send(&mut self) -> Result<(), Error> {
self.test_ctx.tx_instantiate2(
self.key,
self.chain_name,
self.admin,
self.code_id.expect("missing builder param code_id"),
self.label.expect("missing builder param label"),
self.msg.as_ref().expect("missing builder param msg"),
self.funds.as_ref(),
self.salt.as_ref().expect("missing builder param salt"),
self.fix_msg,
)
}
}

impl TestContext {
pub fn build_tx_instantiate2<'a>(&'a mut self) -> Instantiate2TxBuilder<'a> {
Instantiate2TxBuilder {
key: DEFAULT_KEY,
chain_name: NEUTRON_CHAIN_NAME,
admin: None,
code_id: None,
label: None,
msg: None,
funds: None,
salt: None,
fix_msg: None,
test_ctx: self,
}
}

fn tx_instantiate2(
&mut self,
key: &str,
chain_name: &str,
admin: Option<&str>,
code_id: u64,
label: &str,
msg: &Value,
funds: Option<&Coin>,
salt: &str,
fix_msg: Option<bool>,
) -> Result<(), Error> {
let chain = self.get_chain(chain_name);

// Optional flags
let admin_part = admin
.map(|admin| format!("--admin {admin} "))
.unwrap_or(String::from("--no-admin "));
let amt_part = funds
.map(|funds| format!("--amount {funds} "))
.unwrap_or_default();
let fix_msg_part = fix_msg
.map(|fix_msg| format!("--fix_msg {fix_msg} "))
.unwrap_or_default();

let receipt = chain.rb.tx(
&format!("tx wasm instantiate2 {code_id} {msg} {salt} --label {label} {admin_part}{amt_part}{fix_msg_part}--from {key}"),
false,
)?;

self.guard_tx_errors(
chain_name,
receipt
.get("txhash")
.and_then(|receipt| receipt.as_str())
.ok_or(Error::TxMissingLogs)?,
)?;

Ok(())
}
}
Loading

0 comments on commit 6738206

Please sign in to comment.