From 5d4376560e193b795fdfdcb5f3f79696c9ca3f67 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 14 Nov 2024 18:42:42 +0100 Subject: [PATCH 01/92] init osmo gamm test; bump neutron_osmosis chainconfig osmo version to 26+ --- .../chains/neutron_osmosis.json | 4 +- local-interchaintest/examples/osmo_gamm.rs | 43 +++++++++++++++++++ local-interchaintest/src/utils/manager.rs | 2 + local-interchaintest/src/utils/mod.rs | 2 + local-interchaintest/src/utils/osmosis.rs | 1 + 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 local-interchaintest/examples/osmo_gamm.rs create mode 100644 local-interchaintest/src/utils/osmosis.rs diff --git a/local-interchaintest/chains/neutron_osmosis.json b/local-interchaintest/chains/neutron_osmosis.json index 785f5c3d..a570fdeb 100644 --- a/local-interchaintest/chains/neutron_osmosis.json +++ b/local-interchaintest/chains/neutron_osmosis.json @@ -189,7 +189,7 @@ "binary": "osmosisd", "bech32_prefix": "osmo", "docker_image": { - "version": "v25.0.4", + "version": "v26.0.2", "repository": "ghcr.io/strangelove-ventures/heighliner/osmosis" }, "gas_prices": "0.0025%DENOM%", @@ -230,4 +230,4 @@ } } ] -} \ No newline at end of file +} diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs new file mode 100644 index 00000000..307350ab --- /dev/null +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -0,0 +1,43 @@ +use std::error::Error; + +use local_interchaintest::utils::{ + manager::{setup_manager, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME}, + LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, +}; + +use localic_utils::{ + ConfigChainBuilder, TestContextBuilder, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME, +}; +use valence_program_manager::program_config_builder::ProgramConfigBuilder; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let mut test_ctx = TestContextBuilder::default() + .with_unwrap_raw_logs(true) + .with_api_url(LOCAL_IC_API_URL) + .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) + .with_chain(ConfigChainBuilder::default_neutron().build()?) + .with_chain(ConfigChainBuilder::default_osmosis().build()?) + .with_log_file_path(LOGS_FILE_PATH) + .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) + .build()?; + + setup_manager( + &mut test_ctx, + NEUTRON_OSMO_CONFIG_FILE, + vec![GAIA_CHAIN_NAME], + vec![OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME], + )?; + + let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); + let neutron_domain = + valence_program_manager::domain::Domain::CosmosCosmwasm(NEUTRON_CHAIN_NAME.to_string()); + let osmo_domain = + valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); + + // TODO: set up the GAMM pool + + Ok(()) +} diff --git a/local-interchaintest/src/utils/manager.rs b/local-interchaintest/src/utils/manager.rs index 36656c75..4dcbfdd2 100644 --- a/local-interchaintest/src/utils/manager.rs +++ b/local-interchaintest/src/utils/manager.rs @@ -26,6 +26,8 @@ pub const GENERIC_IBC_TRANSFER_NAME: &str = "valence-generic-ibc-transfer-librar pub const NEUTRON_IBC_TRANSFER_NAME: &str = "valence-neutron-ibc-transfer-library"; pub const ASTROPORT_LPER_NAME: &str = "valence_astroport_lper"; pub const ASTROPORT_WITHDRAWER_NAME: &str = "valence_astroport_withdrawer"; +pub const OSMOSIS_GAMM_LPER_NAME: &str = "valence_osmosis_gamm_lper"; +pub const OSMOSIS_GAMM_LWER_NAME: &str = "valence_osmosis_gamm_withdrawer"; /// Those contracts will always be uploaded because each program needs them const BASIC_CONTRACTS: [&str; 2] = [PROCESSOR_NAME, BASE_ACCOUNT_NAME]; diff --git a/local-interchaintest/src/utils/mod.rs b/local-interchaintest/src/utils/mod.rs index 842cabda..562318a7 100644 --- a/local-interchaintest/src/utils/mod.rs +++ b/local-interchaintest/src/utils/mod.rs @@ -2,6 +2,7 @@ pub mod authorization; pub mod base_account; pub mod ibc; pub mod manager; +pub mod osmosis; pub mod persistence; pub mod polytone; pub mod processor; @@ -10,6 +11,7 @@ pub mod relayer; // Local-ic chain configs files pub const NEUTRON_CONFIG_FILE: &str = "neutron.json"; pub const NEUTRON_JUNO_CONFIG_FILE: &str = "neutron_juno.json"; +pub const NEUTRON_OSMO_CONFIG_FILE: &str = "neutron_osmosis.json"; // Path of all valence contracts pub const VALENCE_ARTIFACTS_PATH: &str = "artifacts"; diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs new file mode 100644 index 00000000..f1b6c441 --- /dev/null +++ b/local-interchaintest/src/utils/osmosis.rs @@ -0,0 +1 @@ +pub mod gamm {} From 26616816925bdf5de731eb33a61c7a143a87cf2b Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 14 Nov 2024 19:06:15 +0100 Subject: [PATCH 02/92] creating gamm pool --- local-interchaintest/examples/osmo_gamm.rs | 47 +++++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 307350ab..7c441dc2 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -5,10 +5,13 @@ use local_interchaintest::utils::{ LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; +use localic_std::modules::bank; use localic_utils::{ ConfigChainBuilder, TestContextBuilder, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, - NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, + OSMOSIS_CHAIN_NAME, }; +use log::info; use valence_program_manager::program_config_builder::ProgramConfigBuilder; fn main() -> Result<(), Box> { @@ -37,7 +40,47 @@ fn main() -> Result<(), Box> { let osmo_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); - // TODO: set up the GAMM pool + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); + test_ctx + .build_tx_transfer() + .with_chain_name(NEUTRON_CHAIN_NAME) + .with_amount(1_000_000_000u128) + .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) + .with_denom(NEUTRON_CHAIN_DENOM) + .send() + .unwrap(); + std::thread::sleep(std::time::Duration::from_secs(3)); + + let token_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + OSMOSIS_CHAIN_ADMIN_ADDR, + ); + info!("osmosis chain admin addr balances: {:?}", token_balances); + + test_ctx + .build_tx_create_osmo_pool() + .with_weight("uosmo", 1) + .with_weight(&ntrn_on_osmo_denom, 1) + .with_initial_deposit("uosmo", 1) + .with_initial_deposit(&ntrn_on_osmo_denom, 1) + .send()?; + + // Get its id + let pool_id = test_ctx + .get_osmo_pool() + .denoms("uosmo".into(), ntrn_on_osmo_denom) + .get_u64(); + + info!("Gamm pool id: {:?}", pool_id); Ok(()) } From db3f1fdb7b4f14137ecd05e095ce87d83e1951d2 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 15 Nov 2024 13:08:44 +0100 Subject: [PATCH 03/92] add osmo gamm libraries to program manager --- program-manager/Cargo.toml | 4 +++ program-manager/src/library.rs | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/program-manager/Cargo.toml b/program-manager/Cargo.toml index f32dfaa5..031fda47 100644 --- a/program-manager/Cargo.toml +++ b/program-manager/Cargo.toml @@ -32,6 +32,10 @@ valence-authorization = { workspace = true } valence-processor = { workspace = true } valence-program-registry = { workspace = true } valence-forwarder-library = { workspace = true } +valence-osmosis-gamm-lper = { workspace = true } +valence-osmosis-gamm-withdrawer = { workspace = true } +valence-osmosis-cl-lper = { workspace = true } +valence-osmosis-cl-withdrawer = { workspace = true } tokio = { workspace = true } aho-corasick = "1.1" diff --git a/program-manager/src/library.rs b/program-manager/src/library.rs index 568bd5b3..59538f41 100644 --- a/program-manager/src/library.rs +++ b/program-manager/src/library.rs @@ -79,6 +79,8 @@ pub enum LibraryConfig { ValenceReverseSplitterLibrary(valence_reverse_splitter_library::msg::LibraryConfig), ValenceAstroportLper(valence_astroport_lper::msg::LibraryConfig), ValenceAstroportWithdrawer(valence_astroport_withdrawer::msg::LibraryConfig), + ValenceOsmosisGammLper(valence_osmosis_gamm_lper::msg::LibraryConfig), + ValenceOsmosisGammWithdrawer(valence_osmosis_gamm_withdrawer::msg::LibraryConfig), } #[derive( @@ -102,6 +104,8 @@ pub enum LibraryConfigUpdate { ValenceReverseSplitterLibrary(valence_reverse_splitter_library::msg::LibraryConfigUpdate), ValenceAstroportLper(valence_astroport_lper::msg::LibraryConfigUpdate), ValenceAstroportWithdrawer(valence_astroport_withdrawer::msg::LibraryConfigUpdate), + ValenceOsmosisGammLper(valence_osmosis_gamm_lper::msg::LibraryConfigUpdate), + ValenceOsmosisGammWithdrawer(valence_osmosis_gamm_withdrawer::msg::LibraryConfigUpdate), } impl LibraryConfigUpdate { @@ -148,6 +152,22 @@ impl LibraryConfigUpdate { new_config: service_config_update, }) } + LibraryConfigUpdate::ValenceOsmosisGammLper(library_config_update) => { + to_json_binary(&valence_library_utils::msg::ExecuteMsg::< + Empty, + valence_osmosis_gamm_lper::msg::LibraryConfigUpdate, + >::UpdateConfig { + new_config: library_config_update, + }) + } + LibraryConfigUpdate::ValenceOsmosisGammWithdrawer(library_config_update) => { + to_json_binary(&valence_library_utils::msg::ExecuteMsg::< + Empty, + valence_osmosis_gamm_withdrawer::msg::LibraryConfigUpdate, + >::UpdateConfig { + new_config: library_config_update, + }) + } } .map_err(LibraryError::CosmwasmStdError) } @@ -193,6 +213,18 @@ impl LibraryConfig { let json = serde_json::to_string(&config)?; let res = ac.replace_all(&json, &replace_with); + *config = serde_json::from_str(&res)?; + } + LibraryConfig::ValenceOsmosisGammLper(ref mut config) => { + let json = serde_json::to_string(&config)?; + let res = ac.replace_all(&json, &replace_with); + + *config = serde_json::from_str(&res)?; + } + LibraryConfig::ValenceOsmosisGammWithdrawer(ref mut config) => { + let json = serde_json::to_string(&config)?; + let res = ac.replace_all(&json, &replace_with); + *config = serde_json::from_str(&res)?; } } @@ -228,6 +260,16 @@ impl LibraryConfig { processor, config: config.clone(), }), + LibraryConfig::ValenceOsmosisGammLper(config) => to_vec(&InstantiateMsg { + owner, + processor, + config: config.clone(), + }), + LibraryConfig::ValenceOsmosisGammWithdrawer(config) => to_vec(&InstantiateMsg { + owner, + processor, + config: config.clone(), + }), } .map_err(LibraryError::SerdeJsonError) } @@ -255,6 +297,14 @@ impl LibraryConfig { config.pre_validate(api)?; Ok(()) } + LibraryConfig::ValenceOsmosisGammLper(config) => { + config.pre_validate(api)?; + Ok(()) + } + LibraryConfig::ValenceOsmosisGammWithdrawer(config) => { + config.pre_validate(api)?; + Ok(()) + } } } @@ -278,6 +328,12 @@ impl LibraryConfig { LibraryConfig::ValenceAstroportWithdrawer(config) => { Self::find_account_ids(ac, serde_json::to_string(&config)?) } + LibraryConfig::ValenceOsmosisGammLper(config) => { + Self::find_account_ids(ac, serde_json::to_string(&config)?) + } + LibraryConfig::ValenceOsmosisGammWithdrawer(config) => { + Self::find_account_ids(ac, serde_json::to_string(&config)?) + } } } From c7ea87b719de67c3fa1794bd4ce67b7b3f32d6b2 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 15 Nov 2024 16:55:00 +0100 Subject: [PATCH 04/92] setting up polytone contracts pre-manager init --- Cargo.lock | 8 + local-interchaintest/Cargo.toml | 8 +- local-interchaintest/examples/osmo_gamm.rs | 359 +++++++++++++++++++-- local-interchaintest/src/utils/manager.rs | 3 + local-interchaintest/src/utils/mod.rs | 2 + 5 files changed, 343 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 303fcdf3..fec0d39d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2581,6 +2581,10 @@ dependencies = [ "valence-ibc-utils", "valence-library-utils", "valence-neutron-ibc-transfer-library", + "valence-osmosis-cl-lper", + "valence-osmosis-cl-withdrawer", + "valence-osmosis-gamm-lper", + "valence-osmosis-gamm-withdrawer", "valence-processor", "valence-processor-utils", "valence-program-manager", @@ -5462,6 +5466,10 @@ dependencies = [ "valence-library-base", "valence-library-utils", "valence-macros", + "valence-osmosis-cl-lper", + "valence-osmosis-cl-withdrawer", + "valence-osmosis-gamm-lper", + "valence-osmosis-gamm-withdrawer", "valence-processor", "valence-processor-utils", "valence-program-registry", diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 025e4dd5..b2d73fb9 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -33,9 +33,13 @@ valence-forwarder-library = { workspace = true } valence-astroport-lper = { workspace = true } valence-astroport-withdrawer = { workspace = true } valence-astroport-utils = { workspace = true } -valence-program-manager = { workspace = true } -valence-program-registry-utils = { workspace = true } +valence-program-manager = { workspace = true } +valence-program-registry-utils = { workspace = true } valence-ibc-utils = { workspace = true } valence-generic-ibc-transfer-library = { workspace = true } valence-neutron-ibc-transfer-library = { workspace = true } +valence-osmosis-gamm-lper = { workspace = true } +valence-osmosis-gamm-withdrawer = { workspace = true } +valence-osmosis-cl-lper = { workspace = true } +valence-osmosis-cl-withdrawer = { workspace = true } tokio = { workspace = true } diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 7c441dc2..0aa6b2de 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -1,18 +1,81 @@ -use std::error::Error; +use std::{ + error::Error, + time::{Duration, SystemTime}, +}; +use cosmwasm_std_old::Uint64; use local_interchaintest::utils::{ - manager::{setup_manager, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME}, - LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, + manager::{ + setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, + POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + }, + LOCAL_CODE_ID_CACHE_PATH_NEUTRON, LOCAL_CODE_ID_CACHE_PATH_OSMOSIS, LOGS_FILE_PATH, + NEUTRON_OSMO_CONFIG_FILE, POLYTONE_ARTIFACTS_PATH, VALENCE_ARTIFACTS_PATH, }; -use localic_std::modules::bank; +use localic_std::{ + modules::{bank, cosmwasm::CosmWasm}, + relayer::Relayer, +}; use localic_utils::{ - ConfigChainBuilder, TestContextBuilder, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, - NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, - OSMOSIS_CHAIN_NAME, + utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, + GAIA_CHAIN_NAME, LOCAL_IC_API_URL, NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, + NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_DENOM, + OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; -use valence_program_manager::program_config_builder::ProgramConfigBuilder; +use valence_authorization_utils::{ + authorization_message::{Message, MessageDetails, MessageType}, + builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, +}; +use valence_program_manager::{ + account::{AccountInfo, AccountType}, + library::{LibraryConfig, LibraryInfo}, + program_config_builder::ProgramConfigBuilder, +}; + +fn setup_gamm_pool( + test_ctx: &mut TestContext, + denom_1: &str, + denom_2: &str, +) -> Result> { + info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); + test_ctx + .build_tx_transfer() + .with_chain_name(NEUTRON_CHAIN_NAME) + .with_amount(1_000_000_000u128) + .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) + .with_denom(NEUTRON_CHAIN_DENOM) + .send() + .unwrap(); + std::thread::sleep(std::time::Duration::from_secs(3)); + + let token_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + OSMOSIS_CHAIN_ADMIN_ADDR, + ); + info!("osmosis chain admin addr balances: {:?}", token_balances); + + test_ctx + .build_tx_create_osmo_pool() + .with_weight(denom_1, 1) + .with_weight(denom_2, 1) + .with_initial_deposit(denom_1, 100_000_000) + .with_initial_deposit(denom_2, 100_000_000) + .send()?; + + // Get its id + let pool_id = test_ctx + .get_osmo_pool() + .denoms(denom_1.into(), denom_2.to_string()) + .get_u64(); + + info!("Gamm pool id: {:?}", pool_id); + + Ok(pool_id) +} fn main() -> Result<(), Box> { env_logger::init(); @@ -40,6 +103,17 @@ fn main() -> Result<(), Box> { let osmo_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); + let gamm_input_acc = builder.add_account(AccountInfo::new( + "gamm_input".to_string(), + &osmo_domain, + AccountType::default(), + )); + let gamm_output_acc = builder.add_account(AccountInfo::new( + "gamm_output".to_string(), + &osmo_domain, + AccountType::default(), + )); + let ntrn_on_osmo_denom = test_ctx .get_ibc_denom() .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) @@ -47,40 +121,255 @@ fn main() -> Result<(), Box> { .dest(OSMOSIS_CHAIN_NAME) .get(); - info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); - test_ctx - .build_tx_transfer() - .with_chain_name(NEUTRON_CHAIN_NAME) - .with_amount(1_000_000_000u128) - .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) - .with_denom(NEUTRON_CHAIN_DENOM) - .send() + let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + + let gamm_lper_config = valence_osmosis_gamm_lper::msg::LibraryConfig { + input_addr: gamm_input_acc.clone(), + output_addr: gamm_output_acc.clone(), + lp_config: valence_osmosis_gamm_lper::msg::LiquidityProviderConfig { + pool_id, + pool_asset_1: OSMOSIS_CHAIN_DENOM.to_string(), + pool_asset_2: ntrn_on_osmo_denom.to_string(), + }, + }; + + let gamm_lper_library = builder.add_library(LibraryInfo::new( + "test_gamm_lp".to_string(), + &osmo_domain, + LibraryConfig::ValenceOsmosisGammLper(gamm_lper_config.clone()), + )); + + builder.add_link( + &gamm_lper_library, + vec![&gamm_input_acc], + vec![&gamm_output_acc], + ); + + let gamm_lper_function = AtomicFunctionBuilder::new() + .with_contract_address(gamm_lper_library.clone()) + .with_message_details(MessageDetails { + message_type: MessageType::CosmwasmExecuteMsg, + message: Message { + name: "provide_liquidity".to_string(), + params_restrictions: None, + }, + }) + .build(); + + let gamm_lper_subroutine = AtomicSubroutineBuilder::new() + .with_function(gamm_lper_function) + .build(); + + let provide_liquidity_authorization = AuthorizationBuilder::new() + .with_subroutine(gamm_lper_subroutine) + .build(); + + builder.add_authorization(provide_liquidity_authorization); + + let mut program_config = builder.build(); + + let (ntrn_note, osmo_note) = setup_polytone(&mut test_ctx); + + use_manager_init(&mut program_config)?; + + Ok(()) +} + +fn setup_polytone(test_ctx: &mut TestContext) -> (String, String) { + // Upload all Polytone contracts to both Neutron and Osmosis + let mut uploader = test_ctx.build_tx_upload_contracts(); + uploader + .send_with_local_cache(POLYTONE_ARTIFACTS_PATH, LOCAL_CODE_ID_CACHE_PATH_NEUTRON) .unwrap(); - std::thread::sleep(std::time::Duration::from_secs(3)); - let token_balances = bank::get_balance( + uploader + .with_chain_name(OSMOSIS_CHAIN_NAME) + .send_with_local_cache(POLYTONE_ARTIFACTS_PATH, LOCAL_CODE_ID_CACHE_PATH_OSMOSIS) + .unwrap(); + + // Before setting up the external domains and the processor on the external domain, we are going to set up polytone and predict the proxy addresses on both sides + let mut polytone_note_on_neutron = test_ctx + .get_contract() + .contract(POLYTONE_NOTE_NAME) + .get_cw(); + + let mut polytone_voice_on_neutron = test_ctx + .get_contract() + .contract(POLYTONE_VOICE_NAME) + .get_cw(); + + let polytone_proxy_on_neutron = test_ctx + .get_contract() + .contract(POLYTONE_PROXY_NAME) + .get_cw(); + + let mut polytone_note_on_osmosis = test_ctx + .get_contract() + .src(OSMOSIS_CHAIN_NAME) + .contract(POLYTONE_NOTE_NAME) + .get_cw(); + + let mut polytone_voice_on_osmosis = test_ctx + .get_contract() + .src(OSMOSIS_CHAIN_NAME) + .contract(POLYTONE_VOICE_NAME) + .get_cw(); + + let polytone_proxy_on_osmosis = test_ctx + .get_contract() + .src(OSMOSIS_CHAIN_NAME) + .contract(POLYTONE_PROXY_NAME) + .get_cw(); + + let polytone_note_instantiate_msg = polytone_note::msg::InstantiateMsg { + pair: None, + block_max_gas: Uint64::new(3010000), + }; + + let neutron_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { + proxy_code_id: Uint64::new(polytone_proxy_on_neutron.code_id.unwrap()), + block_max_gas: Uint64::new(3010000), + contract_addr_len: None, + }; + + let osmo_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { + proxy_code_id: Uint64::new(polytone_proxy_on_osmosis.code_id.unwrap()), + block_max_gas: Uint64::new(3010000), + contract_addr_len: None, + }; + + info!("Instantiating polytone contracts on both domains"); + let polytone_note_on_neutron_address = polytone_note_on_neutron + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&polytone_note_instantiate_msg).unwrap(), + "polytone-note-neutron", + None, + "", + ) + .unwrap() + .address; + + info!("Polytone Note on Neutron: {polytone_note_on_neutron_address}"); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_voice_on_neutron_address = polytone_voice_on_neutron + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&neutron_polytone_voice_instantiate_msg).unwrap(), + "polytone-voice-neutron", + None, + "", + ) + .unwrap() + .address; + + info!("Polytone voice on neutron: {polytone_voice_on_neutron_address}",); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_note_on_osmo_address = polytone_note_on_osmosis + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&polytone_note_instantiate_msg).unwrap(), + "polytone-note-osmosis", + None, + &format!("--fees {}{}", 5000, OSMOSIS_CHAIN_DENOM), + ) + .unwrap() + .address; + + info!("polytone note on osmosis: {polytone_note_on_osmo_address}"); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_voice_on_osmo_address = polytone_voice_on_osmosis + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&osmo_polytone_voice_instantiate_msg).unwrap(), + "polytone-voice-osmosis", + None, + &format!("--fees {}{}", 5000, OSMOSIS_CHAIN_DENOM), + ) + .unwrap() + .address; + info!("Polytone Voice on osmo: {polytone_voice_on_osmo_address}"); + + std::thread::sleep(std::time::Duration::from_secs(2)); + info!("Creating WASM connections..."); + + let relayer = Relayer::new( test_ctx .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - OSMOSIS_CHAIN_ADMIN_ADDR, + .get_request_builder(NEUTRON_CHAIN_NAME), ); - info!("osmosis chain admin addr balances: {:?}", token_balances); - test_ctx - .build_tx_create_osmo_pool() - .with_weight("uosmo", 1) - .with_weight(&ntrn_on_osmo_denom, 1) - .with_initial_deposit("uosmo", 1) - .with_initial_deposit(&ntrn_on_osmo_denom, 1) - .send()?; + polytone_note_on_neutron + .create_wasm_connection( + &relayer, + "neutron-osmosis", + &CosmWasm::new_from_existing( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + None, + None, + Some(polytone_voice_on_osmo_address.clone()), + ), + "unordered", + "polytone-1", + ) + .unwrap(); - // Get its id - let pool_id = test_ctx - .get_osmo_pool() - .denoms("uosmo".into(), ntrn_on_osmo_denom) - .get_u64(); + polytone_voice_on_neutron + .create_wasm_connection( + &relayer, + "neutron-osmosis", + &CosmWasm::new_from_existing( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + None, + None, + Some(polytone_note_on_osmo_address.clone()), + ), + "unordered", + "polytone-1", + ) + .unwrap(); - info!("Gamm pool id: {:?}", pool_id); + // Give some time to make sure the channels are open + std::thread::sleep(Duration::from_secs(15)); - Ok(()) + // Get the connection ids so that we can predict the proxy addresses + let neutron_channels = relayer.get_channels(NEUTRON_CHAIN_ID).unwrap(); + + let connection_id_neutron_to_osmo = neutron_channels.iter().find_map(|neutron_channel| { + if neutron_channel.port_id == format!("wasm.{}", polytone_note_on_neutron_address.clone()) { + neutron_channel.connection_hops.first().cloned() + } else { + None + } + }); + info!( + "Connection ID of Wasm connection neutron to osmo: {:?}", + connection_id_neutron_to_osmo + ); + + let osmo_channels = relayer.get_channels(OSMOSIS_CHAIN_ID).unwrap(); + + let connection_id_osmo_to_neutron = osmo_channels.iter().find_map(|osmo_channel| { + if osmo_channel.port_id == format!("wasm.{}", polytone_note_on_osmo_address.clone()) { + osmo_channel.connection_hops.first().cloned() + } else { + None + } + }); + info!( + "Connection ID of Wasm connection osmo to neutron: {:?}", + connection_id_osmo_to_neutron + ); + + ( + polytone_note_on_neutron_address, + polytone_note_on_osmo_address, + ) } diff --git a/local-interchaintest/src/utils/manager.rs b/local-interchaintest/src/utils/manager.rs index 4dcbfdd2..247e7d0d 100644 --- a/local-interchaintest/src/utils/manager.rs +++ b/local-interchaintest/src/utils/manager.rs @@ -28,6 +28,9 @@ pub const ASTROPORT_LPER_NAME: &str = "valence_astroport_lper"; pub const ASTROPORT_WITHDRAWER_NAME: &str = "valence_astroport_withdrawer"; pub const OSMOSIS_GAMM_LPER_NAME: &str = "valence_osmosis_gamm_lper"; pub const OSMOSIS_GAMM_LWER_NAME: &str = "valence_osmosis_gamm_withdrawer"; +pub const POLYTONE_NOTE_NAME: &str = "polytone_note"; +pub const POLYTONE_VOICE_NAME: &str = "polytone_voice"; +pub const POLYTONE_PROXY_NAME: &str = "polytone_proxy"; /// Those contracts will always be uploaded because each program needs them const BASIC_CONTRACTS: [&str; 2] = [PROCESSOR_NAME, BASE_ACCOUNT_NAME]; diff --git a/local-interchaintest/src/utils/mod.rs b/local-interchaintest/src/utils/mod.rs index 562318a7..d7a1a28d 100644 --- a/local-interchaintest/src/utils/mod.rs +++ b/local-interchaintest/src/utils/mod.rs @@ -27,6 +27,8 @@ pub const LOCAL_CODE_ID_CACHE_PATH_NEUTRON: &str = pub const LOCAL_CODE_ID_CACHE_PATH_JUNO: &str = "local-interchaintest/code_id_cache_juno.json"; pub const LOCAL_CODE_ID_CACHE_PATH_PERSISTENCE: &str = "local-interchaintest/code_id_cache_persistence.json"; +pub const LOCAL_CODE_ID_CACHE_PATH_OSMOSIS: &str = + "local-interchaintest/code_id_cache_osmosis.json"; pub const GAS_FLAGS: &str = "--gas=auto --gas-adjustment=3.0"; pub const NTRN_DENOM: &str = "untrn"; From 284c1e7f0d66093720bda0f7ec565c5728d30cdb Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 15 Nov 2024 18:33:26 +0100 Subject: [PATCH 05/92] storing polytone info in global config --- local-interchaintest/examples/osmo_gamm.rs | 124 ++++++++++++++------- local-interchaintest/src/utils/manager.rs | 25 ++++- program-manager/src/bridge.rs | 7 +- program-manager/src/domain/cosmos_cw.rs | 4 +- program-manager/src/program_config.rs | 14 ++- 5 files changed, 120 insertions(+), 54 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 0aa6b2de..157d7d5e 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, error::Error, time::{Duration, SystemTime}, }; @@ -6,8 +7,8 @@ use std::{ use cosmwasm_std_old::Uint64; use local_interchaintest::utils::{ manager::{ - setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, - POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, + OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, LOCAL_CODE_ID_CACHE_PATH_NEUTRON, LOCAL_CODE_ID_CACHE_PATH_OSMOSIS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, POLYTONE_ARTIFACTS_PATH, VALENCE_ARTIFACTS_PATH, @@ -24,12 +25,15 @@ use localic_utils::{ OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; +use tokio::runtime::Runtime; use valence_authorization_utils::{ authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, }; use valence_program_manager::{ account::{AccountInfo, AccountType}, + bridge::{Bridge, PolytoneBridgeInfo, PolytoneSingleChainInfo}, + config::GLOBAL_CONFIG, library::{LibraryConfig, LibraryInfo}, program_config_builder::ProgramConfigBuilder, }; @@ -94,7 +98,13 @@ fn main() -> Result<(), Box> { &mut test_ctx, NEUTRON_OSMO_CONFIG_FILE, vec![GAIA_CHAIN_NAME], - vec![OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME], + vec![ + OSMOSIS_GAMM_LPER_NAME, + OSMOSIS_GAMM_LWER_NAME, + POLYTONE_NOTE_NAME, + POLYTONE_VOICE_NAME, + POLYTONE_PROXY_NAME, + ], )?; let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); @@ -168,25 +178,14 @@ fn main() -> Result<(), Box> { let mut program_config = builder.build(); - let (ntrn_note, osmo_note) = setup_polytone(&mut test_ctx); + setup_polytone(&mut test_ctx); use_manager_init(&mut program_config)?; Ok(()) } -fn setup_polytone(test_ctx: &mut TestContext) -> (String, String) { - // Upload all Polytone contracts to both Neutron and Osmosis - let mut uploader = test_ctx.build_tx_upload_contracts(); - uploader - .send_with_local_cache(POLYTONE_ARTIFACTS_PATH, LOCAL_CODE_ID_CACHE_PATH_NEUTRON) - .unwrap(); - - uploader - .with_chain_name(OSMOSIS_CHAIN_NAME) - .send_with_local_cache(POLYTONE_ARTIFACTS_PATH, LOCAL_CODE_ID_CACHE_PATH_OSMOSIS) - .unwrap(); - +fn setup_polytone(test_ctx: &mut TestContext) { // Before setting up the external domains and the processor on the external domain, we are going to set up polytone and predict the proxy addresses on both sides let mut polytone_note_on_neutron = test_ctx .get_contract() @@ -342,34 +341,77 @@ fn setup_polytone(test_ctx: &mut TestContext) -> (String, String) { // Get the connection ids so that we can predict the proxy addresses let neutron_channels = relayer.get_channels(NEUTRON_CHAIN_ID).unwrap(); - let connection_id_neutron_to_osmo = neutron_channels.iter().find_map(|neutron_channel| { - if neutron_channel.port_id == format!("wasm.{}", polytone_note_on_neutron_address.clone()) { - neutron_channel.connection_hops.first().cloned() - } else { - None - } - }); - info!( - "Connection ID of Wasm connection neutron to osmo: {:?}", - connection_id_neutron_to_osmo - ); + let neutron_to_osmo_polytone_channel = neutron_channels + .iter() + .find_map(|neutron_channel| { + if neutron_channel.port_id + == format!("wasm.{}", polytone_note_on_neutron_address.clone()) + { + Some(neutron_channel.clone()) + } else { + None + } + }) + .unwrap(); let osmo_channels = relayer.get_channels(OSMOSIS_CHAIN_ID).unwrap(); - let connection_id_osmo_to_neutron = osmo_channels.iter().find_map(|osmo_channel| { - if osmo_channel.port_id == format!("wasm.{}", polytone_note_on_osmo_address.clone()) { - osmo_channel.connection_hops.first().cloned() - } else { - None - } - }); - info!( - "Connection ID of Wasm connection osmo to neutron: {:?}", - connection_id_osmo_to_neutron + let osmo_to_neutron_polytone_channel = osmo_channels + .iter() + .find_map(|osmo_channel| { + if osmo_channel.port_id == format!("wasm.{}", polytone_note_on_osmo_address.clone()) { + Some(osmo_channel.clone()) + } else { + None + } + }) + .unwrap(); + + let osmo_polytone_info = PolytoneSingleChainInfo { + voice_addr: polytone_voice_on_osmo_address, + note_addr: polytone_note_on_osmo_address, + other_note_port: neutron_to_osmo_polytone_channel.port_id, + connection_id: osmo_to_neutron_polytone_channel + .connection_hops + .first() + .cloned() + .unwrap(), + channel_id: osmo_to_neutron_polytone_channel.channel_id, + }; + let neutron_polytone_info = PolytoneSingleChainInfo { + voice_addr: polytone_voice_on_neutron_address, + note_addr: polytone_note_on_neutron_address, + other_note_port: osmo_to_neutron_polytone_channel.port_id, + connection_id: neutron_to_osmo_polytone_channel + .connection_hops + .first() + .cloned() + .unwrap(), + channel_id: neutron_to_osmo_polytone_channel.channel_id, + }; + + let osmo_to_neutron_polytone_bridge_info: HashMap = + HashMap::from([(NEUTRON_CHAIN_NAME.to_string(), neutron_polytone_info)]); + + let neutron_to_osmo_polytone_bridge_info: HashMap = + HashMap::from([(OSMOSIS_CHAIN_NAME.to_string(), osmo_polytone_info)]); + + let mut osmo_bridge_map: HashMap = HashMap::new(); + osmo_bridge_map.insert( + NEUTRON_CHAIN_NAME.to_string(), + Bridge::Polytone(neutron_to_osmo_polytone_bridge_info), + ); + + let mut neutron_bridge_map: HashMap = HashMap::new(); + neutron_bridge_map.insert( + OSMOSIS_CHAIN_NAME.to_string(), + Bridge::Polytone(osmo_to_neutron_polytone_bridge_info), ); - ( - polytone_note_on_neutron_address, - polytone_note_on_osmo_address, - ) + let mut gc = get_global_config(); + + gc.bridges + .insert(OSMOSIS_CHAIN_NAME.to_string(), osmo_bridge_map); + gc.bridges + .insert(NEUTRON_CHAIN_NAME.to_string(), neutron_bridge_map); } diff --git a/local-interchaintest/src/utils/manager.rs b/local-interchaintest/src/utils/manager.rs index 247e7d0d..8856c141 100644 --- a/local-interchaintest/src/utils/manager.rs +++ b/local-interchaintest/src/utils/manager.rs @@ -13,6 +13,8 @@ use valence_program_manager::{ update_program, }; +use crate::utils::POLYTONE_ARTIFACTS_PATH; + const LOG_FILE_PATH: &str = "local-interchaintest/configs/logs.json"; pub const REGISTRY_NAME: &str = "valence_program_registry"; @@ -95,8 +97,25 @@ pub fn setup_manager( for contract_name in contracts.iter() { let mut uploader = test_ctx.build_tx_upload_contracts(); uploader.with_chain_name(chain_name); - let (path, contrat_wasm_name, contract_name) = - get_contract_path(chain_name, contract_name, artifacts_dir.as_str()); + + let (path, contract_wasm_name, contract_name) = match contract_name.as_ref() { + POLYTONE_NOTE_NAME => ( + format!("{}/{}.wasm", POLYTONE_ARTIFACTS_PATH, POLYTONE_NOTE_NAME), + POLYTONE_NOTE_NAME, + POLYTONE_NOTE_NAME, + ), + POLYTONE_VOICE_NAME => ( + format!("{}/{}.wasm", POLYTONE_ARTIFACTS_PATH, POLYTONE_VOICE_NAME), + POLYTONE_VOICE_NAME, + POLYTONE_VOICE_NAME, + ), + POLYTONE_PROXY_NAME => ( + format!("{}/{}.wasm", POLYTONE_ARTIFACTS_PATH, POLYTONE_PROXY_NAME), + POLYTONE_PROXY_NAME, + POLYTONE_PROXY_NAME, + ), + _ => get_contract_path(chain_name, contract_name, artifacts_dir.as_str()), + }; // Upload contract uploader.send_single_contract(path.as_str()).unwrap(); @@ -104,7 +123,7 @@ pub fn setup_manager( // get its code id let code_id = test_ctx .get_contract() - .contract(contrat_wasm_name) + .contract(contract_wasm_name) .get_cw() .code_id .unwrap(); diff --git a/program-manager/src/bridge.rs b/program-manager/src/bridge.rs index 8c7f7d34..dabbf6f6 100644 --- a/program-manager/src/bridge.rs +++ b/program-manager/src/bridge.rs @@ -7,13 +7,14 @@ pub enum Bridge { /// This is the details we need for the bridge to predict the address of the proxy /// https://github.com/DA0-DA0/polytone/blob/main/contracts/main/voice/src/contract.rs#L186 /// - /// Polytone is 1-to-1 bridge (1 note <> 1 voice), so we need this information for every chain that we are connected to. + /// Polytone is 1-to-1 bridge (1 note <> 1 voice), so we need this + /// information for every chain that we are connected to. Polytone(PolytoneBridgeInfo), } /// This type represents the bridge info between 2 chains. -/// should always and only hold 2 elements, where the key is the chain name and the value is the bridge info -/// between those 2 chains. +/// should always and only hold 2 elements, where the key is the +/// chain name and the value is the bridge info between those 2 chains. pub type PolytoneBridgeInfo = HashMap; /// This struct represent the data that we need for polytone in a single chain diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 66e4d739..1c364d9b 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -99,7 +99,7 @@ impl CosmosCosmwasmConnector { let gc = GLOBAL_CONFIG.lock().await; let chain_info: &ChainInfo = gc.get_chain_info(chain_name)?; let code_ids: &HashMap = gc.get_code_ids(chain_name)?; - + println!("code ids of chain {chain_name}: {:?}", code_ids); let grpc = GrpcClient::new(&chain_info.grpc).await.context(format!( "Failed to create new client for: {}", chain_info.name @@ -1099,7 +1099,7 @@ impl CosmosCosmwasmConnector { .get_polytone_info() } else { return Err(anyhow!( - "Failed to get brdige info, none of the provded chains is the main chain" + "Failed to get bridge info, none of the provided chains is the main chain" ) .into()); }; diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index 87f54c4a..fad7ba55 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -131,13 +131,16 @@ impl ProgramConfig { .set_processor_addr(neutron_domain.clone(), main_processor_addr); // init processors and bridge accounts on all other domains - // For mainnet we need to instantiate a bridge account for each processor instantiated on other domains - // For other domains, we need to instantiate a bridge account on the main domain for the authorization contract + // For mainnet we need to instantiate a bridge account for each + // processor instantiated on other domains + // For other domains, we need to instantiate a bridge account + // on the main domain for the authorization contract for domain in all_domains.iter() { if domain != &neutron_domain { let mut connector = connectors.get_or_create_connector(domain).await?; - // get the authorization bridge account address on the other domain (to be the admon of the processor) + // get the authorization bridge account address on the + // other domain (to be the admin of the processor) let authorization_bridge_account_addr = connector .get_address_bridge( authorization_addr.as_str(), @@ -152,7 +155,8 @@ impl ProgramConfig { .get_address(self.id, "valence_processor", "valence_processor") .await?; - // Instantiate the processor on the other domain, the admin is the bridge account address of the authorization contract + // Instantiate the processor on the other domain, the admin is + // the bridge account address of the authorization contract connector .instantiate_processor( self.id, @@ -213,7 +217,7 @@ impl ProgramConfig { // Add processor bridge account info by domain self.authorization_data .set_processor_bridge_addr(domain.clone(), processor_bridge_account_addr); - }; + } } // We need to manually drop neutron connector here because we finished with it for now. From 824299f42770bf6bed9fd38e2b0d7693468138f0 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 15 Nov 2024 19:23:56 +0100 Subject: [PATCH 06/92] wip: setting polytone config on non-main domains --- local-interchaintest/examples/osmo_gamm.rs | 6 +++-- program-manager/src/program_config.rs | 31 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 157d7d5e..85b4d42b 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -178,14 +178,14 @@ fn main() -> Result<(), Box> { let mut program_config = builder.build(); - setup_polytone(&mut test_ctx); + setup_polytone(&mut test_ctx)?; use_manager_init(&mut program_config)?; Ok(()) } -fn setup_polytone(test_ctx: &mut TestContext) { +fn setup_polytone(test_ctx: &mut TestContext) -> Result<(), Box> { // Before setting up the external domains and the processor on the external domain, we are going to set up polytone and predict the proxy addresses on both sides let mut polytone_note_on_neutron = test_ctx .get_contract() @@ -414,4 +414,6 @@ fn setup_polytone(test_ctx: &mut TestContext) { .insert(OSMOSIS_CHAIN_NAME.to_string(), osmo_bridge_map); gc.bridges .insert(NEUTRON_CHAIN_NAME.to_string(), neutron_bridge_map); + + Ok(()) } diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index fad7ba55..2e49fcf0 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -1,13 +1,17 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use cosmwasm_schema::schemars::JsonSchema; +use cosmwasm_std::Uint64; use serde::{Deserialize, Serialize}; +use tokio::runtime::Runtime; use valence_authorization_utils::authorization::AuthorizationInfo; use valence_library_utils::{GetId, Id}; use crate::{ account::{AccountInfo, AccountType, InstantiateAccountData}, + bridge::Bridge, + config::GLOBAL_CONFIG, connectors::Connectors, domain::Domain, error::{ManagerError, ManagerResult}, @@ -155,6 +159,31 @@ impl ProgramConfig { .get_address(self.id, "valence_processor", "valence_processor") .await?; + // load the global config to access the bridge information + let rt = Runtime::new().unwrap(); + let gc = rt.block_on(GLOBAL_CONFIG.lock()); + + // get the polytone bridge info from currently observed domain to neutron + println!("observing domain: {:?}", domain); + + let polytone_bridge_info = gc + .get_bridge_info(NEUTRON_CHAIN, domain.get_chain_name())? + .get_polytone_info(); + + let polytone_config = match polytone_bridge_info.get(NEUTRON_CHAIN) { + Some(chain_info) => { + // TODO: predict this address correctly + let polytone_proxy_address = chain_info.voice_addr.to_string(); + + Some(valence_processor_utils::msg::PolytoneContracts { + polytone_proxy_address, + polytone_note_address: chain_info.note_addr.to_string(), + timeout_seconds: 3_010_000, + }) + } + None => None, + }; + // Instantiate the processor on the other domain, the admin is // the bridge account address of the authorization contract connector @@ -162,7 +191,7 @@ impl ProgramConfig { self.id, salt, authorization_bridge_account_addr.clone(), - None, + polytone_config, ) .await?; From a6a090d6113fae76a8d40980a49c712161982833 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 18 Nov 2024 14:06:41 +0100 Subject: [PATCH 07/92] wip: polytone integration in program manager --- local-interchaintest/examples/osmo_gamm.rs | 19 ++++++------------- program-manager/src/program_config.rs | 4 ++-- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 85b4d42b..a3184b9b 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -10,8 +10,7 @@ use local_interchaintest::utils::{ get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - LOCAL_CODE_ID_CACHE_PATH_NEUTRON, LOCAL_CODE_ID_CACHE_PATH_OSMOSIS, LOGS_FILE_PATH, - NEUTRON_OSMO_CONFIG_FILE, POLYTONE_ARTIFACTS_PATH, VALENCE_ARTIFACTS_PATH, + LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; use localic_std::{ @@ -25,15 +24,13 @@ use localic_utils::{ OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; -use tokio::runtime::Runtime; use valence_authorization_utils::{ authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, }; use valence_program_manager::{ account::{AccountInfo, AccountType}, - bridge::{Bridge, PolytoneBridgeInfo, PolytoneSingleChainInfo}, - config::GLOBAL_CONFIG, + bridge::{Bridge, PolytoneSingleChainInfo}, library::{LibraryConfig, LibraryInfo}, program_config_builder::ProgramConfigBuilder, }; @@ -396,22 +393,18 @@ fn setup_polytone(test_ctx: &mut TestContext) -> Result<(), Box> { let neutron_to_osmo_polytone_bridge_info: HashMap = HashMap::from([(OSMOSIS_CHAIN_NAME.to_string(), osmo_polytone_info)]); - let mut osmo_bridge_map: HashMap = HashMap::new(); - osmo_bridge_map.insert( - NEUTRON_CHAIN_NAME.to_string(), - Bridge::Polytone(neutron_to_osmo_polytone_bridge_info), - ); - let mut neutron_bridge_map: HashMap = HashMap::new(); neutron_bridge_map.insert( OSMOSIS_CHAIN_NAME.to_string(), Bridge::Polytone(osmo_to_neutron_polytone_bridge_info), ); + neutron_bridge_map.insert( + NEUTRON_CHAIN_NAME.to_string(), + Bridge::Polytone(neutron_to_osmo_polytone_bridge_info), + ); let mut gc = get_global_config(); - gc.bridges - .insert(OSMOSIS_CHAIN_NAME.to_string(), osmo_bridge_map); gc.bridges .insert(NEUTRON_CHAIN_NAME.to_string(), neutron_bridge_map); diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index 2e49fcf0..ad700d2f 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -160,12 +160,12 @@ impl ProgramConfig { .await?; // load the global config to access the bridge information - let rt = Runtime::new().unwrap(); - let gc = rt.block_on(GLOBAL_CONFIG.lock()); + let gc = Runtime::new().unwrap().block_on(GLOBAL_CONFIG.lock()); // get the polytone bridge info from currently observed domain to neutron println!("observing domain: {:?}", domain); + // get from neutron to current domain bridge info let polytone_bridge_info = gc .get_bridge_info(NEUTRON_CHAIN, domain.get_chain_name())? .get_polytone_info(); From 5ab9d5b98f16c9d613bd25fec1fde5d5c366204c Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 18 Nov 2024 14:08:28 +0100 Subject: [PATCH 08/92] cleanup gc load in program manager --- program-manager/src/program_config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index ad700d2f..7908610f 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -160,7 +160,7 @@ impl ProgramConfig { .await?; // load the global config to access the bridge information - let gc = Runtime::new().unwrap().block_on(GLOBAL_CONFIG.lock()); + let gc = GLOBAL_CONFIG.lock().await; // get the polytone bridge info from currently observed domain to neutron println!("observing domain: {:?}", domain); From 34d7bd9b0bb43926fc4a87bb825b46ad411817d3 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 18 Nov 2024 14:33:19 +0100 Subject: [PATCH 09/92] adjust get_bridge_info --- program-manager/src/domain/cosmos_cw.rs | 19 ++++--------- program-manager/src/program_config.rs | 38 +++++++++++-------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 1c364d9b..25f0e247 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -1090,21 +1090,14 @@ impl CosmosCosmwasmConnector { receive_chain: &str, ) -> Result { let gc = GLOBAL_CONFIG.lock().await; - - let info = if main_chain == sender_chain { - gc.get_bridge_info(sender_chain, receive_chain)? - .get_polytone_info() - } else if main_chain == receive_chain { - gc.get_bridge_info(receive_chain, sender_chain)? - .get_polytone_info() + let (sender_chain, other_chain) = if main_chain == sender_chain { + (sender_chain, receive_chain) } else { - return Err(anyhow!( - "Failed to get bridge info, none of the provided chains is the main chain" - ) - .into()); + (receive_chain, sender_chain) }; - - info.get(receive_chain) + gc.get_bridge_info(sender_chain, other_chain)? + .get_polytone_info() + .get(receive_chain) .context(format!("Bridge info not found for: {}", receive_chain)) .map_err(CosmosCosmwasmError::Error) .cloned() diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index 7908610f..b826679f 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -149,7 +149,7 @@ impl ProgramConfig { .get_address_bridge( authorization_addr.as_str(), NEUTRON_CHAIN, - domain.get_chain_name(), + NEUTRON_CHAIN, domain.get_chain_name(), ) .await?; @@ -170,19 +170,23 @@ impl ProgramConfig { .get_bridge_info(NEUTRON_CHAIN, domain.get_chain_name())? .get_polytone_info(); - let polytone_config = match polytone_bridge_info.get(NEUTRON_CHAIN) { - Some(chain_info) => { - // TODO: predict this address correctly - let polytone_proxy_address = chain_info.voice_addr.to_string(); + // Get the processor bridge account address on main domain + let processor_bridge_account_addr = neutron_connector + .get_address_bridge( + processor_addr.as_str(), + NEUTRON_CHAIN, + domain.get_chain_name(), + NEUTRON_CHAIN, + ) + .await?; - Some(valence_processor_utils::msg::PolytoneContracts { - polytone_proxy_address, - polytone_note_address: chain_info.note_addr.to_string(), - timeout_seconds: 3_010_000, - }) + let polytone_config = polytone_bridge_info.get(NEUTRON_CHAIN).map(|chain_info| { + valence_processor_utils::msg::PolytoneContracts { + polytone_proxy_address: processor_bridge_account_addr.to_string(), + polytone_note_address: chain_info.note_addr.to_string(), + timeout_seconds: 3_010_000, } - None => None, - }; + }); // Instantiate the processor on the other domain, the admin is // the bridge account address of the authorization contract @@ -195,16 +199,6 @@ impl ProgramConfig { ) .await?; - // Get the processor bridge account address on main domain - let processor_bridge_account_addr = neutron_connector - .get_address_bridge( - processor_addr.as_str(), - NEUTRON_CHAIN, - domain.get_chain_name(), - NEUTRON_CHAIN, - ) - .await?; - // construct and add the `ExternalDomain` info to the authorization contract // Adding external domain to the authorization contract will create the bridge account on that domain neutron_connector From ce31c1ae04e0359a7d7ace9e0decab31781c6833 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 12:22:45 +0100 Subject: [PATCH 10/92] manager fixes --- local-interchaintest/examples/osmo_gamm.rs | 14 ++---- local-interchaintest/src/utils/manager.rs | 3 +- program-manager/src/domain/cosmos_cw.rs | 41 ++++++++-------- program-manager/src/domain/mod.rs | 1 - program-manager/src/helpers.rs | 16 +++++++ program-manager/src/program_config.rs | 56 ++++++++++------------ 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index a3184b9b..0bf416b0 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -105,7 +105,7 @@ fn main() -> Result<(), Box> { )?; let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); - let neutron_domain = + let _neutron_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(NEUTRON_CHAIN_NAME.to_string()); let osmo_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); @@ -388,20 +388,16 @@ fn setup_polytone(test_ctx: &mut TestContext) -> Result<(), Box> { }; let osmo_to_neutron_polytone_bridge_info: HashMap = - HashMap::from([(NEUTRON_CHAIN_NAME.to_string(), neutron_polytone_info)]); - - let neutron_to_osmo_polytone_bridge_info: HashMap = - HashMap::from([(OSMOSIS_CHAIN_NAME.to_string(), osmo_polytone_info)]); + HashMap::from([ + (NEUTRON_CHAIN_NAME.to_string(), neutron_polytone_info), + (OSMOSIS_CHAIN_NAME.to_string(), osmo_polytone_info), + ]); let mut neutron_bridge_map: HashMap = HashMap::new(); neutron_bridge_map.insert( OSMOSIS_CHAIN_NAME.to_string(), Bridge::Polytone(osmo_to_neutron_polytone_bridge_info), ); - neutron_bridge_map.insert( - NEUTRON_CHAIN_NAME.to_string(), - Bridge::Polytone(neutron_to_osmo_polytone_bridge_info), - ); let mut gc = get_global_config(); diff --git a/local-interchaintest/src/utils/manager.rs b/local-interchaintest/src/utils/manager.rs index 8856c141..774ddfe1 100644 --- a/local-interchaintest/src/utils/manager.rs +++ b/local-interchaintest/src/utils/manager.rs @@ -98,7 +98,7 @@ pub fn setup_manager( let mut uploader = test_ctx.build_tx_upload_contracts(); uploader.with_chain_name(chain_name); - let (path, contract_wasm_name, contract_name) = match contract_name.as_ref() { + let (path, contract_wasm_name, contract_name) = match *contract_name { POLYTONE_NOTE_NAME => ( format!("{}/{}.wasm", POLYTONE_ARTIFACTS_PATH, POLYTONE_NOTE_NAME), POLYTONE_NOTE_NAME, @@ -123,6 +123,7 @@ pub fn setup_manager( // get its code id let code_id = test_ctx .get_contract() + .src(chain_name) .contract(contract_wasm_name) .get_cw() .code_id diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 25f0e247..50c6d625 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -234,11 +234,15 @@ impl Connector for CosmosCosmwasmConnector { receiving_chain: &str, ) -> ConnectorResult { // Get the checksum of the code id + println!("get_address_bridge scope code ids: {:?}", self.code_ids); let code_id = *self .code_ids .get("polytone_proxy") .context(format!("Code id not found for: {}", "polytone_proxy")) .map_err(CosmosCosmwasmError::Error)?; + + println!("polytone proxy code id: {:?}", code_id); + let receiving_chain_bridge_info = self .get_bridge_info(main_chain, sender_chain, receiving_chain) .await?; @@ -252,24 +256,16 @@ impl Connector for CosmosCosmwasmConnector { .finalize() .to_vec(); - let addr = self - .wallet - .client - .proto_query::( - QueryBuildAddressRequest { - code_hash: hex::encode(checksum.clone()), - creator_address: receiving_chain_bridge_info.voice_addr, - salt: hex::encode(salt.clone()), - }, - "/cosmwasm.wasm.v1.Query/BuildAddress", - ) - .await - .context(format!( - "Failed to query the instantiate2 address: {:?}", - checksum - )) - .map_err(CosmosCosmwasmError::Error)? - .address; + let addr_canonical = instantiate2_address( + &checksum, + &addr_canonicalize(&self.prefix, self.wallet.account_address.as_str()).unwrap(), + &salt, + ) + .context("Failed to instantiate2 address") + .map_err(CosmosCosmwasmError::Error)?; + + let addr = + addr_humanize(&self.prefix, &addr_canonical).map_err(CosmosCosmwasmError::Error)?; Ok(addr) } @@ -316,7 +312,6 @@ impl Connector for CosmosCosmwasmConnector { async fn instantiate_library( &mut self, program_id: u64, - auth_addr: String, processor_addr: String, library_id: u64, library_config: LibraryConfig, @@ -334,7 +329,7 @@ impl Connector for CosmosCosmwasmConnector { let m = MsgInstantiateContract2 { sender: self.wallet.account_address.clone(), - admin: auth_addr, + admin: processor_addr, code_id, label: format!( "program-{}|library-{}-{}", @@ -481,7 +476,7 @@ impl Connector for CosmosCosmwasmConnector { } let bridge = self - .get_bridge_info(main_domain, main_domain, domain) + .get_bridge_info(main_domain, domain, main_domain) .await?; let external_domain = valence_authorization_utils::msg::ExternalDomainInfo { @@ -1090,15 +1085,17 @@ impl CosmosCosmwasmConnector { receive_chain: &str, ) -> Result { let gc = GLOBAL_CONFIG.lock().await; + let (sender_chain, other_chain) = if main_chain == sender_chain { (sender_chain, receive_chain) } else { (receive_chain, sender_chain) }; + gc.get_bridge_info(sender_chain, other_chain)? .get_polytone_info() .get(receive_chain) - .context(format!("Bridge info not found for: {}", receive_chain)) + .context(format!("Bridge info not found for: {}", other_chain)) .map_err(CosmosCosmwasmError::Error) .cloned() } diff --git a/program-manager/src/domain/mod.rs b/program-manager/src/domain/mod.rs index 670f5a4e..6c855049 100644 --- a/program-manager/src/domain/mod.rs +++ b/program-manager/src/domain/mod.rs @@ -134,7 +134,6 @@ pub trait Connector: fmt::Debug + Send + Sync { async fn instantiate_library( &mut self, program_id: u64, - auth_addr: String, processor_addr: String, library_id: u64, library_config: LibraryConfig, diff --git a/program-manager/src/helpers.rs b/program-manager/src/helpers.rs index eeb70231..9409dbc2 100644 --- a/program-manager/src/helpers.rs +++ b/program-manager/src/helpers.rs @@ -1,7 +1,11 @@ +use std::collections::HashMap; + use anyhow::anyhow; use bech32::{encode, primitives::decode::CheckedHrpstring, Bech32, Hrp}; use cosmwasm_std::CanonicalAddr; +use crate::config::{ConfigResult, GLOBAL_CONFIG}; + fn validate_length(bytes: &[u8]) -> Result<(), anyhow::Error> { match bytes.len() { 1..=255 => Ok(()), @@ -32,3 +36,15 @@ pub fn addr_humanize(prefix: &str, canonical: &CanonicalAddr) -> Result(prefix, canonical.as_slice()).map_err(|_| anyhow!("Bech32 encoding error")) } + +pub async fn get_polytone_info( + main_chain: &str, + other_chain: &str, +) -> ConfigResult> { + let gc = GLOBAL_CONFIG.lock().await; + // get from neutron to current domain bridge info + Ok(gc + .get_bridge_info(main_chain, other_chain)? + .get_polytone_info() + .clone()) +} diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index b826679f..d3f47128 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -1,20 +1,18 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use cosmwasm_schema::schemars::JsonSchema; -use cosmwasm_std::Uint64; use serde::{Deserialize, Serialize}; -use tokio::runtime::Runtime; use valence_authorization_utils::authorization::AuthorizationInfo; use valence_library_utils::{GetId, Id}; use crate::{ account::{AccountInfo, AccountType, InstantiateAccountData}, - bridge::Bridge, config::GLOBAL_CONFIG, connectors::Connectors, domain::Domain, error::{ManagerError, ManagerResult}, + helpers::get_polytone_info, library::LibraryInfo, macros::ensure, NEUTRON_CHAIN, @@ -159,16 +157,19 @@ impl ProgramConfig { .get_address(self.id, "valence_processor", "valence_processor") .await?; - // load the global config to access the bridge information - let gc = GLOBAL_CONFIG.lock().await; + let polytone_bridge_info = + get_polytone_info(NEUTRON_CHAIN, domain.get_chain_name()).await?; - // get the polytone bridge info from currently observed domain to neutron - println!("observing domain: {:?}", domain); - - // get from neutron to current domain bridge info - let polytone_bridge_info = gc - .get_bridge_info(NEUTRON_CHAIN, domain.get_chain_name())? - .get_polytone_info(); + let polytone_config = + polytone_bridge_info + .get(domain.get_chain_name()) + .map( + |chain_info| valence_processor_utils::msg::PolytoneContracts { + polytone_proxy_address: authorization_bridge_account_addr.clone(), + polytone_note_address: chain_info.note_addr.to_string(), + timeout_seconds: 3_010_000, + }, + ); // Get the processor bridge account address on main domain let processor_bridge_account_addr = neutron_connector @@ -180,14 +181,6 @@ impl ProgramConfig { ) .await?; - let polytone_config = polytone_bridge_info.get(NEUTRON_CHAIN).map(|chain_info| { - valence_processor_utils::msg::PolytoneContracts { - polytone_proxy_address: processor_bridge_account_addr.to_string(), - polytone_note_address: chain_info.note_addr.to_string(), - timeout_seconds: 3_010_000, - } - }); - // Instantiate the processor on the other domain, the admin is // the bridge account address of the authorization contract connector @@ -344,7 +337,6 @@ impl ProgramConfig { domain_connector .instantiate_library( self.id, - authorization_addr.clone(), processor_addr, link.library_id, library.config, @@ -597,17 +589,17 @@ impl ProgramConfig { } // Verify authorization and processor bridge accounts were created correctly - for (domain, authorization_bridge_addr) in - self.authorization_data.authorization_bridge_addrs.iter() - { - let mut connector = connectors - .get_or_create_connector(&Domain::from_string(domain.to_string())?) - .await?; - - connector - .verify_bridge_account(authorization_bridge_addr.clone()) - .await?; - } + // for (domain, authorization_bridge_addr) in + // self.authorization_data.authorization_bridge_addrs.iter() + // { + // let mut connector = connectors + // .get_or_create_connector(&Domain::from_string(domain.to_string())?) + // .await?; + + // connector + // .verify_bridge_account(authorization_bridge_addr.clone()) + // .await?; + // } Ok(()) } From e73390faf94df5738b133b7956976a91035ab131 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 12:24:15 +0100 Subject: [PATCH 11/92] clippyfmt --- local-interchaintest/examples/osmo_gamm.rs | 6 +----- local-interchaintest/src/utils/base_account.rs | 2 +- program-manager/src/program_config.rs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 0bf416b0..7332c4c3 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -1,8 +1,4 @@ -use std::{ - collections::HashMap, - error::Error, - time::{Duration, SystemTime}, -}; +use std::{collections::HashMap, error::Error, time::Duration}; use cosmwasm_std_old::Uint64; use local_interchaintest::utils::{ diff --git a/local-interchaintest/src/utils/base_account.rs b/local-interchaintest/src/utils/base_account.rs index 3cc3b8c6..0518355d 100644 --- a/local-interchaintest/src/utils/base_account.rs +++ b/local-interchaintest/src/utils/base_account.rs @@ -75,7 +75,7 @@ pub fn approve_library( GAS_FLAGS, flags .map(|mut s| { - if !s.starts_with(" ") { + if !s.starts_with(' ') { s.insert(0, ' '); } s diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index d3f47128..8f342de2 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -8,7 +8,6 @@ use valence_library_utils::{GetId, Id}; use crate::{ account::{AccountInfo, AccountType, InstantiateAccountData}, - config::GLOBAL_CONFIG, connectors::Connectors, domain::Domain, error::{ManagerError, ManagerResult}, From c498862f666a9f0500b2e0998bd7f2194ed6fe59 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 13:33:49 +0100 Subject: [PATCH 12/92] funding input acc; wip: processing the lp message --- local-interchaintest/examples/osmo_gamm.rs | 167 ++++++++++++++++++--- program-manager/src/program_update.rs | 4 +- 2 files changed, 148 insertions(+), 23 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 7332c4c3..92f696af 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -1,16 +1,21 @@ use std::{collections::HashMap, error::Error, time::Duration}; +use cosmwasm_std::Binary; use cosmwasm_std_old::Uint64; use local_interchaintest::utils::{ manager::{ get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, + processor::tick_processor, + GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; use localic_std::{ - modules::{bank, cosmwasm::CosmWasm}, + modules::{ + bank, + cosmwasm::{contract_execute, CosmWasm}, + }, relayer::Relayer, }; use localic_utils::{ @@ -23,6 +28,8 @@ use log::info; use valence_authorization_utils::{ authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, + domain::Domain, + msg::ProcessorMessage, }; use valence_program_manager::{ account::{AccountInfo, AccountType}, @@ -87,6 +94,15 @@ fn main() -> Result<(), Box> { .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) .build()?; + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + setup_manager( &mut test_ctx, NEUTRON_OSMO_CONFIG_FILE, @@ -101,30 +117,22 @@ fn main() -> Result<(), Box> { )?; let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); - let _neutron_domain = - valence_program_manager::domain::Domain::CosmosCosmwasm(NEUTRON_CHAIN_NAME.to_string()); let osmo_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); - let gamm_input_acc = builder.add_account(AccountInfo::new( + let gamm_input_acc_info = AccountInfo::new( "gamm_input".to_string(), &osmo_domain, AccountType::default(), - )); - let gamm_output_acc = builder.add_account(AccountInfo::new( + ); + let gamm_output_acc_info = AccountInfo::new( "gamm_output".to_string(), &osmo_domain, AccountType::default(), - )); - - let ntrn_on_osmo_denom = test_ctx - .get_ibc_denom() - .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) - .src(NEUTRON_CHAIN_NAME) - .dest(OSMOSIS_CHAIN_NAME) - .get(); + ); - let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + let gamm_input_acc = builder.add_account(gamm_input_acc_info); + let gamm_output_acc = builder.add_account(gamm_output_acc_info); let gamm_lper_config = valence_osmosis_gamm_lper::msg::LibraryConfig { input_addr: gamm_input_acc.clone(), @@ -142,6 +150,7 @@ fn main() -> Result<(), Box> { LibraryConfig::ValenceOsmosisGammLper(gamm_lper_config.clone()), )); + // establish the input_acc -> lper_lib -> output_acc link builder.add_link( &gamm_lper_library, vec![&gamm_input_acc], @@ -149,6 +158,7 @@ fn main() -> Result<(), Box> { ); let gamm_lper_function = AtomicFunctionBuilder::new() + .with_domain(Domain::External(osmo_domain.to_string())) .with_contract_address(gamm_lper_library.clone()) .with_message_details(MessageDetails { message_type: MessageType::CosmwasmExecuteMsg, @@ -159,12 +169,13 @@ fn main() -> Result<(), Box> { }) .build(); - let gamm_lper_subroutine = AtomicSubroutineBuilder::new() - .with_function(gamm_lper_function) - .build(); - let provide_liquidity_authorization = AuthorizationBuilder::new() - .with_subroutine(gamm_lper_subroutine) + .with_label("provide_liquidity") + .with_subroutine( + AtomicSubroutineBuilder::new() + .with_function(gamm_lper_function) + .build(), + ) .build(); builder.add_authorization(provide_liquidity_authorization); @@ -174,7 +185,121 @@ fn main() -> Result<(), Box> { setup_polytone(&mut test_ctx)?; use_manager_init(&mut program_config)?; + info!("manager initialized successfully!"); + + let input_acc_addr = program_config + .get_account(gamm_input_acc)? + .addr + .clone() + .unwrap(); + let output_acc_addr = program_config + .get_account(gamm_output_acc)? + .addr + .clone() + .unwrap(); + info!("input_acc_addr: {input_acc_addr}"); + info!("output_acc_addr: {output_acc_addr}"); + let input_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + let output_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &output_acc_addr, + ); + info!("input_acc_balances: {:?}", input_acc_balances); + info!("output_acc_balances: {:?}", output_acc_balances); + + info!("funding the input account..."); + bank::send( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + DEFAULT_KEY, + &input_acc_addr, + &[ + cosmwasm_std_old::Coin { + denom: ntrn_on_osmo_denom.to_string(), + amount: 1_000_000u128.into(), + }, + cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 1_000_000u128.into(), + }, + ], + &cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 1_000_000u128.into(), + }, + ) + .unwrap(); + + std::thread::sleep(Duration::from_secs(3)); + + let input_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + info!("input_acc_balances: {:?}", input_acc_balances); + + // Get authorization and processor contract addresses + let authorization_contract_address = + program_config.authorization_data.authorization_addr.clone(); + let processor_contract_address = program_config + .get_processor_addr(&osmo_domain.to_string()) + .unwrap(); + + info!("authorization contract address: {authorization_contract_address}"); + info!("processor contract address: {processor_contract_address}"); + + let lp_message = ProcessorMessage::CosmwasmExecuteMsg { + msg: Binary::from( + serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_gamm_lper::msg::FunctionMsgs::ProvideDoubleSidedLiquidity { + expected_spot_price: None, + }, + ), + ) + .unwrap(), + ), + }; + let provide_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( + valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { + label: "provide_liquidity".to_string(), + messages: vec![lp_message], + ttl: None, + }, + ); + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + DEFAULT_KEY, + &serde_json::to_string(&provide_liquidity_msg).unwrap(), + "--fees=2000000untrn", + ) + .unwrap(); + + info!("Messages sent to the authorization contract!"); + std::thread::sleep(std::time::Duration::from_secs(5)); + + info!("Ticking processor and executing config update..."); + tick_processor( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + DEFAULT_KEY, + &processor_contract_address, + ); Ok(()) } diff --git a/program-manager/src/program_update.rs b/program-manager/src/program_update.rs index fb0db7c6..66dd30f6 100644 --- a/program-manager/src/program_update.rs +++ b/program-manager/src/program_update.rs @@ -21,7 +21,7 @@ use crate::{ NEUTRON_CHAIN, }; -/// The job of the update, is to output a set of instructions to the user to update the program configuration. +/// The job of the update, is to output a set of instructions to the user to update the program configuration. /// The user can only update library configs and authorizations. /// You can set the owner to change the owner of the program /// You can provide a list of library updates to perform @@ -84,7 +84,7 @@ impl ProgramConfigUpdate { // If we have an owner set, we add the update owner instruction if let Some(new_owner) = self.owner.clone() { - config.owner = new_owner.clone(); + config.owner = new_owner.to_string(); // Create instruction to change owner instructions.push_back( From 345325f16e795519c1d2734ae4ccce096ff7ee6c Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 17:14:25 +0100 Subject: [PATCH 13/92] wip: passing messages to osmosis processor --- local-interchaintest/examples/osmo_gamm.rs | 181 +++++++++++++-------- program-manager/src/domain/cosmos_cw.rs | 16 +- program-manager/src/program_config.rs | 42 +++-- 3 files changed, 148 insertions(+), 91 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 92f696af..f174a543 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -7,7 +7,7 @@ use local_interchaintest::utils::{ get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - processor::tick_processor, + processor::{get_processor_queue_items, tick_processor}, GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; @@ -26,6 +26,7 @@ use localic_utils::{ }; use log::info; use valence_authorization_utils::{ + authorization::Priority, authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, domain::Domain, @@ -38,49 +39,6 @@ use valence_program_manager::{ program_config_builder::ProgramConfigBuilder, }; -fn setup_gamm_pool( - test_ctx: &mut TestContext, - denom_1: &str, - denom_2: &str, -) -> Result> { - info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); - test_ctx - .build_tx_transfer() - .with_chain_name(NEUTRON_CHAIN_NAME) - .with_amount(1_000_000_000u128) - .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) - .with_denom(NEUTRON_CHAIN_DENOM) - .send() - .unwrap(); - std::thread::sleep(std::time::Duration::from_secs(3)); - - let token_balances = bank::get_balance( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - OSMOSIS_CHAIN_ADMIN_ADDR, - ); - info!("osmosis chain admin addr balances: {:?}", token_balances); - - test_ctx - .build_tx_create_osmo_pool() - .with_weight(denom_1, 1) - .with_weight(denom_2, 1) - .with_initial_deposit(denom_1, 100_000_000) - .with_initial_deposit(denom_2, 100_000_000) - .send()?; - - // Get its id - let pool_id = test_ctx - .get_osmo_pool() - .denoms(denom_1.into(), denom_2.to_string()) - .get_u64(); - - info!("Gamm pool id: {:?}", pool_id); - - Ok(pool_id) -} - fn main() -> Result<(), Box> { env_logger::init(); @@ -119,6 +77,8 @@ fn main() -> Result<(), Box> { let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); let osmo_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); + let ntrn_domain = + valence_program_manager::domain::Domain::CosmosCosmwasm(NEUTRON_CHAIN_NAME.to_string()); let gamm_input_acc_info = AccountInfo::new( "gamm_input".to_string(), @@ -158,27 +118,27 @@ fn main() -> Result<(), Box> { ); let gamm_lper_function = AtomicFunctionBuilder::new() - .with_domain(Domain::External(osmo_domain.to_string())) + .with_domain(Domain::External(OSMOSIS_CHAIN_NAME.to_string())) .with_contract_address(gamm_lper_library.clone()) .with_message_details(MessageDetails { message_type: MessageType::CosmwasmExecuteMsg, message: Message { - name: "provide_liquidity".to_string(), + name: "process_function".to_string(), params_restrictions: None, }, }) .build(); - let provide_liquidity_authorization = AuthorizationBuilder::new() - .with_label("provide_liquidity") - .with_subroutine( - AtomicSubroutineBuilder::new() - .with_function(gamm_lper_function) - .build(), - ) - .build(); - - builder.add_authorization(provide_liquidity_authorization); + builder.add_authorization( + AuthorizationBuilder::new() + .with_label("provide_liquidity") + .with_subroutine( + AtomicSubroutineBuilder::new() + .with_function(gamm_lper_function) + .build(), + ) + .build(), + ); let mut program_config = builder.build(); @@ -252,12 +212,16 @@ fn main() -> Result<(), Box> { // Get authorization and processor contract addresses let authorization_contract_address = program_config.authorization_data.authorization_addr.clone(); - let processor_contract_address = program_config + let osmo_processor_contract_address = program_config .get_processor_addr(&osmo_domain.to_string()) .unwrap(); + let ntrn_processor_contract_address = program_config + .get_processor_addr(&ntrn_domain.to_string()) + .unwrap(); info!("authorization contract address: {authorization_contract_address}"); - info!("processor contract address: {processor_contract_address}"); + info!("osmo processor contract address: {osmo_processor_contract_address}"); + info!("ntrn processor contract address: {ntrn_processor_contract_address}"); let lp_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from( @@ -279,27 +243,63 @@ fn main() -> Result<(), Box> { }, ); - contract_execute( + let enqueue_resp = contract_execute( test_ctx .get_request_builder() .get_request_builder(NEUTRON_CHAIN_NAME), &authorization_contract_address, DEFAULT_KEY, &serde_json::to_string(&provide_liquidity_msg).unwrap(), - "--fees=2000000untrn", + GAS_FLAGS, ) .unwrap(); + info!("enqueue authorizations response: {:?}", enqueue_resp); + + info!("provide_liquidity_msg sent to the authorization contract!"); + let mut tries = 0; + loop { + let items = get_processor_queue_items( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + Priority::Medium, + ); + println!("Items on osmosis: {:?}", items); + tries += 1; + if !items.is_empty() { + info!("Batch found!"); + break; + } + if tries > 10 { + panic!("Batch not found after 10 tries"); + } + + std::thread::sleep(std::time::Duration::from_secs(5)); + } + + info!("Ticking osmo processor..."); + let resp = contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &osmo_processor_contract_address, + DEFAULT_KEY, + &serde_json::to_string( + &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( + valence_processor_utils::msg::PermissionlessMsg::Tick {}, + ), + ) + .unwrap(), + &format!( + "--gas=auto --gas-adjustment=3.0 --fees {}{}", + 5_000_000, OSMOSIS_CHAIN_DENOM + ), + ) + .unwrap(); + info!("osmo processor tick response: {:?}", resp); - info!("Messages sent to the authorization contract!"); - std::thread::sleep(std::time::Duration::from_secs(5)); + std::thread::sleep(std::time::Duration::from_secs(3)); - info!("Ticking processor and executing config update..."); - tick_processor( - &mut test_ctx, - OSMOSIS_CHAIN_NAME, - DEFAULT_KEY, - &processor_contract_address, - ); Ok(()) } @@ -527,3 +527,46 @@ fn setup_polytone(test_ctx: &mut TestContext) -> Result<(), Box> { Ok(()) } + +fn setup_gamm_pool( + test_ctx: &mut TestContext, + denom_1: &str, + denom_2: &str, +) -> Result> { + info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); + test_ctx + .build_tx_transfer() + .with_chain_name(NEUTRON_CHAIN_NAME) + .with_amount(1_000_000_000u128) + .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) + .with_denom(NEUTRON_CHAIN_DENOM) + .send() + .unwrap(); + std::thread::sleep(std::time::Duration::from_secs(3)); + + let token_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + OSMOSIS_CHAIN_ADMIN_ADDR, + ); + info!("osmosis chain admin addr balances: {:?}", token_balances); + + test_ctx + .build_tx_create_osmo_pool() + .with_weight(denom_1, 1) + .with_weight(denom_2, 1) + .with_initial_deposit(denom_1, 100_000_000) + .with_initial_deposit(denom_2, 100_000_000) + .send()?; + + // Get its id + let pool_id = test_ctx + .get_osmo_pool() + .denoms(denom_1.into(), denom_2.to_string()) + .get_u64(); + + info!("Gamm pool id: {:?}", pool_id); + + Ok(pool_id) +} diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 50c6d625..8ff52d2d 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -23,7 +23,7 @@ use cosmos_grpc_client::{ QueryContractInfoRequest, QuerySmartContractStateRequest, }, }, - cosmrs::bip32::secp256k1::sha2::{digest::Update, Digest, Sha256}, + cosmrs::bip32::secp256k1::sha2::{digest::Update, Digest, Sha256, Sha512}, BroadcastMode, Decimal, GrpcClient, ProstMsgNameToAny, Wallet, }; use cosmwasm_std::{from_json, instantiate2_address, to_json_binary}; @@ -249,16 +249,20 @@ impl Connector for CosmosCosmwasmConnector { let checksum = self.get_checksum(code_id).await?; - let salt = Sha256::new() - .chain(receiving_chain_bridge_info.connection_id) - .chain(receiving_chain_bridge_info.other_note_port) - .chain(sender_addr) + let salt = Sha512::new() + .chain_update(receiving_chain_bridge_info.connection_id.as_bytes()) + .chain_update(receiving_chain_bridge_info.other_note_port.as_bytes()) + .chain_update(sender_addr.as_bytes()) .finalize() .to_vec(); let addr_canonical = instantiate2_address( &checksum, - &addr_canonicalize(&self.prefix, self.wallet.account_address.as_str()).unwrap(), + &addr_canonicalize( + &self.prefix, + receiving_chain_bridge_info.voice_addr.as_str(), + ) + .unwrap(), &salt, ) .context("Failed to instantiate2 address") diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index 8f342de2..6c8fd930 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -45,7 +45,7 @@ pub struct AuthorizationData { /// List of processor bridge addresses by domain /// All addresses are on nuetron, mapping to what domain this bridge account is for /// Key: domain name | Value: processor bridge address on that domain - pub processor_bridge_addrs: BTreeMap, + pub processor_bridge_addrs: Vec, } impl AuthorizationData { @@ -62,8 +62,8 @@ impl AuthorizationData { .insert(domain.to_string(), addr); } - pub fn set_processor_bridge_addr(&mut self, domain: Domain, addr: String) { - self.processor_bridge_addrs.insert(domain.to_string(), addr); + pub fn set_processor_bridge_addr(&mut self, addr: String) { + self.processor_bridge_addrs.push(addr); } } @@ -186,6 +186,7 @@ impl ProgramConfig { .instantiate_processor( self.id, salt, + // TODO: should this really be authorization addr? authorization_bridge_account_addr.clone(), polytone_config, ) @@ -193,6 +194,10 @@ impl ProgramConfig { // construct and add the `ExternalDomain` info to the authorization contract // Adding external domain to the authorization contract will create the bridge account on that domain + println!( + "adding external domain chain name: {:?}", + domain.get_chain_name() + ); neutron_connector .add_external_domain( neutron_domain.get_chain_name(), @@ -231,7 +236,7 @@ impl ProgramConfig { // Add processor bridge account info by domain self.authorization_data - .set_processor_bridge_addr(domain.clone(), processor_bridge_account_addr); + .set_processor_bridge_addr(processor_bridge_account_addr); } } @@ -587,18 +592,23 @@ impl ProgramConfig { connector.verify_processor(processor_addr.clone()).await?; } - // Verify authorization and processor bridge accounts were created correctly - // for (domain, authorization_bridge_addr) in - // self.authorization_data.authorization_bridge_addrs.iter() - // { - // let mut connector = connectors - // .get_or_create_connector(&Domain::from_string(domain.to_string())?) - // .await?; - - // connector - // .verify_bridge_account(authorization_bridge_addr.clone()) - // .await?; - // } + for (domain, authorization_bridge_addr) in + self.authorization_data.authorization_bridge_addrs.iter() + { + let mut connector = connectors + .get_or_create_connector(&Domain::from_string(domain.to_string())?) + .await?; + connector + .verify_bridge_account(authorization_bridge_addr.clone()) + .await?; + } + + for processor_bridge_addr in self.authorization_data.processor_bridge_addrs.iter() { + let mut neutron_connector = connectors.get_or_create_connector(&neutron_domain).await?; + neutron_connector + .verify_bridge_account(processor_bridge_addr.clone()) + .await?; + } Ok(()) } From 1a9b6cb4819a911697aa0845b63846c45b1068f0 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 18:27:14 +0100 Subject: [PATCH 14/92] fix library denom order in test --- local-interchaintest/examples/osmo_gamm.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index f174a543..d7173ebb 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -94,13 +94,16 @@ fn main() -> Result<(), Box> { let gamm_input_acc = builder.add_account(gamm_input_acc_info); let gamm_output_acc = builder.add_account(gamm_output_acc_info); + info!("gamm input acc: {:?}", gamm_input_acc); + info!("gamm output acc: {:?}", gamm_output_acc); + let gamm_lper_config = valence_osmosis_gamm_lper::msg::LibraryConfig { input_addr: gamm_input_acc.clone(), output_addr: gamm_output_acc.clone(), lp_config: valence_osmosis_gamm_lper::msg::LiquidityProviderConfig { pool_id, - pool_asset_1: OSMOSIS_CHAIN_DENOM.to_string(), - pool_asset_2: ntrn_on_osmo_denom.to_string(), + pool_asset_2: OSMOSIS_CHAIN_DENOM.to_string(), + pool_asset_1: ntrn_on_osmo_denom.to_string(), }, }; From 6706b01c6e5035b048b0ed4b670d9190bfe489e2 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 18:49:59 +0100 Subject: [PATCH 15/92] follow liquidity provision with liquidity withdrawal works --- local-interchaintest/examples/osmo_gamm.rs | 179 ++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index d7173ebb..5bdbd5a4 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -7,7 +7,7 @@ use local_interchaintest::utils::{ get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - processor::{get_processor_queue_items, tick_processor}, + processor::get_processor_queue_items, GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; @@ -90,12 +90,19 @@ fn main() -> Result<(), Box> { &osmo_domain, AccountType::default(), ); + let final_output_acc_info = AccountInfo::new( + "final_output".to_string(), + &osmo_domain, + AccountType::default(), + ); let gamm_input_acc = builder.add_account(gamm_input_acc_info); let gamm_output_acc = builder.add_account(gamm_output_acc_info); + let final_output_acc = builder.add_account(final_output_acc_info); info!("gamm input acc: {:?}", gamm_input_acc); info!("gamm output acc: {:?}", gamm_output_acc); + info!("final output acc: {:?}", final_output_acc); let gamm_lper_config = valence_osmosis_gamm_lper::msg::LibraryConfig { input_addr: gamm_input_acc.clone(), @@ -107,18 +114,36 @@ fn main() -> Result<(), Box> { }, }; + let gamm_lwer_config = valence_osmosis_gamm_withdrawer::msg::LibraryConfig { + input_addr: gamm_output_acc.clone(), + output_addr: final_output_acc.clone(), + lw_config: valence_osmosis_gamm_withdrawer::msg::LiquidityWithdrawerConfig { pool_id }, + }; + let gamm_lper_library = builder.add_library(LibraryInfo::new( "test_gamm_lp".to_string(), &osmo_domain, LibraryConfig::ValenceOsmosisGammLper(gamm_lper_config.clone()), )); + let gamm_lwer_library = builder.add_library(LibraryInfo::new( + "test_gamm_lw".to_string(), + &osmo_domain, + LibraryConfig::ValenceOsmosisGammWithdrawer(gamm_lwer_config.clone()), + )); + // establish the input_acc -> lper_lib -> output_acc link builder.add_link( &gamm_lper_library, vec![&gamm_input_acc], vec![&gamm_output_acc], ); + // establish the output_acc -> lwer_lib -> final_output_acc link + builder.add_link( + &gamm_lwer_library, + vec![&gamm_output_acc], + vec![&final_output_acc], + ); let gamm_lper_function = AtomicFunctionBuilder::new() .with_domain(Domain::External(OSMOSIS_CHAIN_NAME.to_string())) @@ -132,6 +157,18 @@ fn main() -> Result<(), Box> { }) .build(); + let gamm_lwer_function = AtomicFunctionBuilder::new() + .with_domain(Domain::External(OSMOSIS_CHAIN_NAME.to_string())) + .with_contract_address(gamm_lwer_library.clone()) + .with_message_details(MessageDetails { + message_type: MessageType::CosmwasmExecuteMsg, + message: Message { + name: "process_function".to_string(), + params_restrictions: None, + }, + }) + .build(); + builder.add_authorization( AuthorizationBuilder::new() .with_label("provide_liquidity") @@ -142,6 +179,16 @@ fn main() -> Result<(), Box> { ) .build(), ); + builder.add_authorization( + AuthorizationBuilder::new() + .with_label("withdraw_liquidity") + .with_subroutine( + AtomicSubroutineBuilder::new() + .with_function(gamm_lwer_function) + .build(), + ) + .build(), + ); let mut program_config = builder.build(); @@ -160,8 +207,15 @@ fn main() -> Result<(), Box> { .addr .clone() .unwrap(); + let final_output_acc_addr = program_config + .get_account(final_output_acc)? + .addr + .clone() + .unwrap(); + info!("input_acc_addr: {input_acc_addr}"); info!("output_acc_addr: {output_acc_addr}"); + info!("final_output_acc_addr: {final_output_acc_addr}"); let input_acc_balances = bank::get_balance( test_ctx @@ -175,8 +229,15 @@ fn main() -> Result<(), Box> { .get_request_builder(OSMOSIS_CHAIN_NAME), &output_acc_addr, ); + let final_output_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &final_output_acc_addr, + ); info!("input_acc_balances: {:?}", input_acc_balances); info!("output_acc_balances: {:?}", output_acc_balances); + info!("final_output_acc_balances: {:?}", final_output_acc_balances); info!("funding the input account..."); bank::send( @@ -303,6 +364,122 @@ fn main() -> Result<(), Box> { std::thread::sleep(std::time::Duration::from_secs(3)); + info!("asserting that providing liquidity worked..."); + let input_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + let output_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &output_acc_addr, + ); + info!("input acc bal: {:?}", input_acc_bal); + info!("output acc bal: {:?}", output_acc_bal); + + assert_eq!(input_acc_bal.len(), 0); + assert_eq!(output_acc_bal.len(), 1); + assert_eq!(output_acc_bal[0].denom, "gamm/pool/1".to_string()); + + info!("confirmed liquidity provision; starting liquidity withdrawal"); + + let lw_message = ProcessorMessage::CosmwasmExecuteMsg { + msg: Binary::from( + serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_gamm_withdrawer::msg::FunctionMsgs::WithdrawLiquidity {}, + ), + ) + .unwrap(), + ), + }; + let withdraw_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( + valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { + label: "withdraw_liquidity".to_string(), + messages: vec![lw_message], + ttl: None, + }, + ); + + let enqueue_resp = contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + DEFAULT_KEY, + &serde_json::to_string(&withdraw_liquidity_msg).unwrap(), + GAS_FLAGS, + ) + .unwrap(); + info!("enqueue authorizations response: {:?}", enqueue_resp); + + info!("withdraw_liquidity_msg sent to the authorization contract!"); + let mut tries = 0; + loop { + let items = get_processor_queue_items( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + Priority::Medium, + ); + println!("Items on osmosis: {:?}", items); + tries += 1; + if !items.is_empty() { + info!("Batch found!"); + break; + } + if tries > 10 { + panic!("Batch not found after 10 tries"); + } + + std::thread::sleep(std::time::Duration::from_secs(5)); + } + + info!("Ticking osmo processor..."); + let resp = contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &osmo_processor_contract_address, + DEFAULT_KEY, + &serde_json::to_string( + &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( + valence_processor_utils::msg::PermissionlessMsg::Tick {}, + ), + ) + .unwrap(), + &format!( + "--gas=auto --gas-adjustment=3.0 --fees {}{}", + 5_000_000, OSMOSIS_CHAIN_DENOM + ), + ) + .unwrap(); + info!("osmo processor tick response: {:?}", resp); + + std::thread::sleep(std::time::Duration::from_secs(3)); + + info!("asserting that withdrawing liquidity worked..."); + let output_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &output_acc_addr, + ); + let final_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &final_output_acc_addr, + ); + info!("output acc bal: {:?}", output_acc_bal); + info!("final acc bal: {:?}", final_acc_bal); + + assert_eq!(output_acc_bal.len(), 0); + assert_eq!(final_acc_bal.len(), 2); + Ok(()) } From 0daaa8d51570c2584bf21fafc8ca1755297114da Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 19:51:33 +0100 Subject: [PATCH 16/92] extend test with main domain authorization module callback validation --- local-interchaintest/examples/osmo_gamm.rs | 64 +++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 5bdbd5a4..a62416d8 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -14,7 +14,7 @@ use local_interchaintest::utils::{ use localic_std::{ modules::{ bank, - cosmwasm::{contract_execute, CosmWasm}, + cosmwasm::{contract_execute, contract_query, CosmWasm}, }, relayer::Relayer, }; @@ -25,10 +25,12 @@ use localic_utils::{ OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; +use serde_json::Value; use valence_authorization_utils::{ authorization::Priority, authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, + callback::ProcessorCallbackInfo, domain::Domain, msg::ProcessorMessage, }; @@ -384,7 +386,65 @@ fn main() -> Result<(), Box> { assert_eq!(output_acc_bal.len(), 1); assert_eq!(output_acc_bal[0].denom, "gamm/pool/1".to_string()); - info!("confirmed liquidity provision; starting liquidity withdrawal"); + info!("confirmed liquidity provision!"); + info!("asserting authorizations callbacks state sync..."); + let mut tries = 0; + loop { + let query_processor_callbacks_response: Value = serde_json::from_value( + contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + &serde_json::to_string( + &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { + start_after: None, + limit: None, + }, + ) + .unwrap(), + )["data"] + .clone(), + ) + .unwrap(); + + info!( + "neutron processor callbacks response: {:?}", + query_processor_callbacks_response + ); + + if query_processor_callbacks_response.is_null() { + info!("No authorization callbacks not found yet..."); + } else { + info!("Callbacks found!"); + let processor_callback_info: Vec = + serde_json::from_value(query_processor_callbacks_response).unwrap(); + info!( + "processor callback info on authorizations: {:?}", + processor_callback_info + ); + + match processor_callback_info[0].execution_result { + valence_authorization_utils::callback::ExecutionResult::Success => { + info!("authorizations module callback result is success!"); + break; + } + _ => { + info!( + "Callback state: {:?}", + processor_callback_info[0].execution_result + ); + } + }; + } + + tries += 1; + if tries == 10 { + panic!("Batch not found after 10 tries"); + } else { + std::thread::sleep(std::time::Duration::from_secs(5)); + } + } let lw_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from( From f7f15ca72fe3ff4b1d938937c40c8a2cfd1178fa Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 20:04:05 +0100 Subject: [PATCH 17/92] fix manager processor instantiation --- program-manager/src/domain/cosmos_cw.rs | 3 ++- program-manager/src/domain/cosmos_evm.rs | 1 + program-manager/src/domain/mod.rs | 1 + program-manager/src/program_config.rs | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 8ff52d2d..295caa7f 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -431,6 +431,7 @@ impl Connector for CosmosCosmwasmConnector { program_id: u64, salt: Vec, admin: String, + authorization: String, polytone_addr: Option, ) -> ConnectorResult<()> { let code_id = *self @@ -440,7 +441,7 @@ impl Connector for CosmosCosmwasmConnector { .map_err(CosmosCosmwasmError::Error)?; let msg = to_vec(&valence_processor_utils::msg::InstantiateMsg { - authorization_contract: admin.clone(), + authorization_contract: authorization, polytone_contracts: polytone_addr, }) .map_err(CosmosCosmwasmError::SerdeJsonError)?; diff --git a/program-manager/src/domain/cosmos_evm.rs b/program-manager/src/domain/cosmos_evm.rs index 3caef876..60338972 100644 --- a/program-manager/src/domain/cosmos_evm.rs +++ b/program-manager/src/domain/cosmos_evm.rs @@ -70,6 +70,7 @@ impl Connector for CosmosEvmConnector { _program_id: u64, _salt: Vec, _admin: String, + _authorization: String, _polytone_addr: Option, ) -> ConnectorResult<()> { unimplemented!("instantiate_processor") diff --git a/program-manager/src/domain/mod.rs b/program-manager/src/domain/mod.rs index 6c855049..3c62b8fc 100644 --- a/program-manager/src/domain/mod.rs +++ b/program-manager/src/domain/mod.rs @@ -146,6 +146,7 @@ pub trait Connector: fmt::Debug + Send + Sync { program_id: u64, salt: Vec, admin: String, + authorization: String, polytone_addr: Option, ) -> ConnectorResult<()>; diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index 6c8fd930..a32e5ccf 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -122,6 +122,7 @@ impl ProgramConfig { self.id, main_processor_salt, authorization_addr.clone(), + authorization_addr.clone(), None, ) .await?; @@ -188,6 +189,7 @@ impl ProgramConfig { salt, // TODO: should this really be authorization addr? authorization_bridge_account_addr.clone(), + authorization_addr.clone(), polytone_config, ) .await?; From 2c519812fa53f7647df8b0fac7eb572bd13d257d Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 20:16:14 +0100 Subject: [PATCH 18/92] rename polytone param in instantiate_processor fn --- program-manager/src/domain/cosmos_cw.rs | 4 ++-- program-manager/src/domain/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 295caa7f..458c64dd 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -432,7 +432,7 @@ impl Connector for CosmosCosmwasmConnector { salt: Vec, admin: String, authorization: String, - polytone_addr: Option, + polytone_config: Option, ) -> ConnectorResult<()> { let code_id = *self .code_ids @@ -442,7 +442,7 @@ impl Connector for CosmosCosmwasmConnector { let msg = to_vec(&valence_processor_utils::msg::InstantiateMsg { authorization_contract: authorization, - polytone_contracts: polytone_addr, + polytone_contracts: polytone_config, }) .map_err(CosmosCosmwasmError::SerdeJsonError)?; diff --git a/program-manager/src/domain/mod.rs b/program-manager/src/domain/mod.rs index 3c62b8fc..d6070da5 100644 --- a/program-manager/src/domain/mod.rs +++ b/program-manager/src/domain/mod.rs @@ -147,7 +147,7 @@ pub trait Connector: fmt::Debug + Send + Sync { salt: Vec, admin: String, authorization: String, - polytone_addr: Option, + polytone_config: Option, ) -> ConnectorResult<()>; /// We need to do 2 things here: From 7186127d5a9b3dd782430f3dbd82dbbdd378a79a Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 20:24:55 +0100 Subject: [PATCH 19/92] confirm withdraw callback result is success on authorizations --- local-interchaintest/examples/osmo_gamm.rs | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index a62416d8..7e574748 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -540,6 +540,75 @@ fn main() -> Result<(), Box> { assert_eq!(output_acc_bal.len(), 0); assert_eq!(final_acc_bal.len(), 2); + info!("asserting authorizations callbacks state sync..."); + let mut tries = 0; + loop { + let query_processor_callbacks_response: Value = serde_json::from_value( + contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + &serde_json::to_string( + &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { + start_after: None, + limit: None, + }, + ) + .unwrap(), + )["data"] + .clone(), + ) + .unwrap(); + + info!( + "neutron processor callbacks response: {:?}", + query_processor_callbacks_response + ); + + if query_processor_callbacks_response.is_null() { + info!("No authorization callbacks not found yet..."); + } else { + info!("Callbacks found!"); + let processor_callback_info: Vec = + serde_json::from_value(query_processor_callbacks_response).unwrap(); + info!( + "processor callback info on authorizations: {:?}", + processor_callback_info + ); + + match processor_callback_info.len() { + 2 => { + match processor_callback_info[1].execution_result { + valence_authorization_utils::callback::ExecutionResult::Success => { + info!("authorizations module callback result is success!"); + break; + } + _ => { + info!( + "Callback state: {:?}", + processor_callback_info[1].execution_result + ); + } + }; + } + _ => { + info!( + "Callback state: {:?}", + processor_callback_info[1].execution_result + ); + } + } + } + + tries += 1; + if tries == 10 { + panic!("Batch not found after 10 tries"); + } else { + std::thread::sleep(std::time::Duration::from_secs(5)); + } + } + Ok(()) } From 47b5464782ccd6318a11d9f55846f7ea1e896433 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 20:44:52 +0100 Subject: [PATCH 20/92] remote domain processor queue length assertion helper --- local-interchaintest/examples/osmo_gamm.rs | 75 +++++++++++----------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 7e574748..fb071649 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -322,26 +322,13 @@ fn main() -> Result<(), Box> { info!("enqueue authorizations response: {:?}", enqueue_resp); info!("provide_liquidity_msg sent to the authorization contract!"); - let mut tries = 0; - loop { - let items = get_processor_queue_items( - &mut test_ctx, - OSMOSIS_CHAIN_NAME, - &osmo_processor_contract_address, - Priority::Medium, - ); - println!("Items on osmosis: {:?}", items); - tries += 1; - if !items.is_empty() { - info!("Batch found!"); - break; - } - if tries > 10 { - panic!("Batch not found after 10 tries"); - } - std::thread::sleep(std::time::Duration::from_secs(5)); - } + confirm_remote_domain_processor_queue_length( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + 1, + ); info!("Ticking osmo processor..."); let resp = contract_execute( @@ -477,26 +464,13 @@ fn main() -> Result<(), Box> { info!("enqueue authorizations response: {:?}", enqueue_resp); info!("withdraw_liquidity_msg sent to the authorization contract!"); - let mut tries = 0; - loop { - let items = get_processor_queue_items( - &mut test_ctx, - OSMOSIS_CHAIN_NAME, - &osmo_processor_contract_address, - Priority::Medium, - ); - println!("Items on osmosis: {:?}", items); - tries += 1; - if !items.is_empty() { - info!("Batch found!"); - break; - } - if tries > 10 { - panic!("Batch not found after 10 tries"); - } - std::thread::sleep(std::time::Duration::from_secs(5)); - } + confirm_remote_domain_processor_queue_length( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + 1, + ); info!("Ticking osmo processor..."); let resp = contract_execute( @@ -879,3 +853,28 @@ fn setup_gamm_pool( Ok(pool_id) } + +fn confirm_remote_domain_processor_queue_length( + test_ctx: &mut TestContext, + processor_domain: &str, + processor_addr: &str, + len: usize, +) { + let mut tries = 0; + loop { + let items = + get_processor_queue_items(test_ctx, processor_domain, processor_addr, Priority::Medium); + println!("Items on {processor_domain}: {:?}", items); + + info!("processor queue length: {len}"); + + if items.len() == len { + break; + } else if tries > 10 { + panic!("Batch not found after 10 tries"); + } + + tries += 1; + std::thread::sleep(std::time::Duration::from_secs(5)); + } +} From 8339f9193149acfbe6415ce29e2c8492dc2030f7 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 21:15:28 +0100 Subject: [PATCH 21/92] more cleanups --- local-interchaintest/examples/osmo_gamm.rs | 216 +++++++++------------ 1 file changed, 89 insertions(+), 127 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index fb071649..63358bb6 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -375,63 +375,13 @@ fn main() -> Result<(), Box> { info!("confirmed liquidity provision!"); info!("asserting authorizations callbacks state sync..."); - let mut tries = 0; - loop { - let query_processor_callbacks_response: Value = serde_json::from_value( - contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &authorization_contract_address, - &serde_json::to_string( - &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { - start_after: None, - limit: None, - }, - ) - .unwrap(), - )["data"] - .clone(), - ) - .unwrap(); - info!( - "neutron processor callbacks response: {:?}", - query_processor_callbacks_response - ); - - if query_processor_callbacks_response.is_null() { - info!("No authorization callbacks not found yet..."); - } else { - info!("Callbacks found!"); - let processor_callback_info: Vec = - serde_json::from_value(query_processor_callbacks_response).unwrap(); - info!( - "processor callback info on authorizations: {:?}", - processor_callback_info - ); - - match processor_callback_info[0].execution_result { - valence_authorization_utils::callback::ExecutionResult::Success => { - info!("authorizations module callback result is success!"); - break; - } - _ => { - info!( - "Callback state: {:?}", - processor_callback_info[0].execution_result - ); - } - }; - } - - tries += 1; - if tries == 10 { - panic!("Batch not found after 10 tries"); - } else { - std::thread::sleep(std::time::Duration::from_secs(5)); - } - } + confirm_authorizations_callback_state( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + &authorization_contract_address, + 0, + ); let lw_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from( @@ -451,7 +401,7 @@ fn main() -> Result<(), Box> { }, ); - let enqueue_resp = contract_execute( + contract_execute( test_ctx .get_request_builder() .get_request_builder(NEUTRON_CHAIN_NAME), @@ -461,7 +411,6 @@ fn main() -> Result<(), Box> { GAS_FLAGS, ) .unwrap(); - info!("enqueue authorizations response: {:?}", enqueue_resp); info!("withdraw_liquidity_msg sent to the authorization contract!"); @@ -515,73 +464,13 @@ fn main() -> Result<(), Box> { assert_eq!(final_acc_bal.len(), 2); info!("asserting authorizations callbacks state sync..."); - let mut tries = 0; - loop { - let query_processor_callbacks_response: Value = serde_json::from_value( - contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &authorization_contract_address, - &serde_json::to_string( - &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { - start_after: None, - limit: None, - }, - ) - .unwrap(), - )["data"] - .clone(), - ) - .unwrap(); - info!( - "neutron processor callbacks response: {:?}", - query_processor_callbacks_response - ); - - if query_processor_callbacks_response.is_null() { - info!("No authorization callbacks not found yet..."); - } else { - info!("Callbacks found!"); - let processor_callback_info: Vec = - serde_json::from_value(query_processor_callbacks_response).unwrap(); - info!( - "processor callback info on authorizations: {:?}", - processor_callback_info - ); - - match processor_callback_info.len() { - 2 => { - match processor_callback_info[1].execution_result { - valence_authorization_utils::callback::ExecutionResult::Success => { - info!("authorizations module callback result is success!"); - break; - } - _ => { - info!( - "Callback state: {:?}", - processor_callback_info[1].execution_result - ); - } - }; - } - _ => { - info!( - "Callback state: {:?}", - processor_callback_info[1].execution_result - ); - } - } - } - - tries += 1; - if tries == 10 { - panic!("Batch not found after 10 tries"); - } else { - std::thread::sleep(std::time::Duration::from_secs(5)); - } - } + confirm_authorizations_callback_state( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + &authorization_contract_address, + 1, + ); Ok(()) } @@ -864,9 +753,11 @@ fn confirm_remote_domain_processor_queue_length( loop { let items = get_processor_queue_items(test_ctx, processor_domain, processor_addr, Priority::Medium); - println!("Items on {processor_domain}: {:?}", items); - - info!("processor queue length: {len}"); + info!( + "{processor_domain} processor queue (len {:?}): {:?}", + items.len(), + items + ); if items.len() == len { break; @@ -878,3 +769,74 @@ fn confirm_remote_domain_processor_queue_length( std::thread::sleep(std::time::Duration::from_secs(5)); } } + +fn confirm_authorizations_callback_state( + test_ctx: &mut TestContext, + authorization_domain: &str, + authorization_addr: &str, + execution_id: u64, +) { + let mut tries = 0; + loop { + let query_processor_callbacks_response: Value = serde_json::from_value( + contract_query( + test_ctx + .get_request_builder() + .get_request_builder(authorization_domain), + authorization_addr, + &serde_json::to_string( + &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { + start_after: None, + limit: None, + }, + ) + .unwrap(), + )["data"] + .clone(), + ) + .unwrap(); + + info!( + "{authorization_domain} authorization mod processor callbacks: {:?}", + query_processor_callbacks_response + ); + + if query_processor_callbacks_response.is_null() { + info!("No authorization callbacks not found yet..."); + } else { + let processor_callback_infos: Vec = + serde_json::from_value(query_processor_callbacks_response).unwrap(); + + let callback_by_id = processor_callback_infos + .iter() + .find(|x| x.execution_id == execution_id); + + info!( + "processor callback #{execution_id} info: {:?}", + callback_by_id + ); + + if let Some(cb) = callback_by_id { + match cb.execution_result { + valence_authorization_utils::callback::ExecutionResult::Success => { + info!("callback #{execution_id} execution = success!"); + break; + } + _ => { + info!( + "callback #{execution_id} execution result: {:?}", + cb.execution_result + ); + } + } + } + } + + tries += 1; + if tries == 10 { + panic!("Batch not found after 10 tries"); + } else { + std::thread::sleep(std::time::Duration::from_secs(5)); + } + } +} From c310e7fea720297827a2fc630995b731258fcc65 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 21:17:04 +0100 Subject: [PATCH 22/92] include workflow in ci --- .github/workflows/check-ci.yml | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-ci.yml b/.github/workflows/check-ci.yml index 8b039e4d..7f30c7cb 100644 --- a/.github/workflows/check-ci.yml +++ b/.github/workflows/check-ci.yml @@ -203,7 +203,7 @@ jobs: cd local-interchaintest /tmp/local-ic start neutron --api-port 42069 & curl --head -X GET --retry 200 --retry-connrefused --retry-delay 5 http://localhost:42069 - + - name: Run 2 party POL Astroport on Neutron example env: RUST_LOG: debug @@ -436,3 +436,48 @@ jobs: - name: Cleanup run: killall local-ic && exit 0 + + local-ic-osmo-gamm-tests: + needs: build + name: Osmosis GAMM e2e lp -> lw run + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get cargo + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: optimized-contracts + path: ./artifacts + + - name: List downloaded files + run: ls -l ./artifacts + + - name: Download local-ic artifact + uses: actions/download-artifact@v3 + with: + name: local-ic + path: /tmp + + - name: Make local-ic executable + run: chmod +x /tmp/local-ic + + - name: Start local-ic and wait for it to be ready + run: | + cd local-interchaintest + /tmp/local-ic start neutron_osmosis --api-port 42069 & + curl --head -X GET --retry 200 --retry-connrefused --retry-delay 5 http://localhost:42069 + + - name: Run osmo gamm lp & lw tests + env: + RUST_LOG: debug + run: cargo run --package local-interchaintest --example osmo_gamm + + - name: Cleanup + run: killall local-ic && exit 0 From 765b1ddaa1363d259846b7ba0c475c8260ffa65e Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 19 Nov 2024 21:20:39 +0100 Subject: [PATCH 23/92] remove logs --- program-manager/src/domain/cosmos_cw.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/program-manager/src/domain/cosmos_cw.rs b/program-manager/src/domain/cosmos_cw.rs index 458c64dd..ec9adefd 100644 --- a/program-manager/src/domain/cosmos_cw.rs +++ b/program-manager/src/domain/cosmos_cw.rs @@ -99,7 +99,7 @@ impl CosmosCosmwasmConnector { let gc = GLOBAL_CONFIG.lock().await; let chain_info: &ChainInfo = gc.get_chain_info(chain_name)?; let code_ids: &HashMap = gc.get_code_ids(chain_name)?; - println!("code ids of chain {chain_name}: {:?}", code_ids); + let grpc = GrpcClient::new(&chain_info.grpc).await.context(format!( "Failed to create new client for: {}", chain_info.name @@ -234,15 +234,12 @@ impl Connector for CosmosCosmwasmConnector { receiving_chain: &str, ) -> ConnectorResult { // Get the checksum of the code id - println!("get_address_bridge scope code ids: {:?}", self.code_ids); let code_id = *self .code_ids .get("polytone_proxy") .context(format!("Code id not found for: {}", "polytone_proxy")) .map_err(CosmosCosmwasmError::Error)?; - println!("polytone proxy code id: {:?}", code_id); - let receiving_chain_bridge_info = self .get_bridge_info(main_chain, sender_chain, receiving_chain) .await?; From 93106615149a80ff351bd05670b45c02863bb928 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 12:40:15 +0100 Subject: [PATCH 24/92] regen schema --- .../schema/valence-program-manager.json | 142 +++++++++++++++++- program-manager/src/program_config.rs | 14 +- 2 files changed, 142 insertions(+), 14 deletions(-) diff --git a/program-manager/schema/valence-program-manager.json b/program-manager/schema/valence-program-manager.json index af2e7aee..b6f9faf7 100644 --- a/program-manager/schema/valence-program-manager.json +++ b/program-manager/schema/valence-program-manager.json @@ -188,9 +188,11 @@ "additionalProperties": false }, "processor_bridge_addrs": { - "description": "List of processor bridge addresses by domain All addresses are on nuetron, mapping to what domain this bridge account is for Key: domain name | Value: processor bridge address on that domain", - "type": "object", - "additionalProperties": false + "description": "List of processor bridge addresses by domain", + "type": "array", + "items": { + "type": "string" + } } }, "additionalProperties": false @@ -677,6 +679,30 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ValenceOsmosisGammLper" + ], + "properties": { + "ValenceOsmosisGammLper": { + "$ref": "#/definitions/LibraryConfigUpdate7" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ValenceOsmosisGammWithdrawer" + ], + "properties": { + "ValenceOsmosisGammWithdrawer": { + "$ref": "#/definitions/LibraryConfigUpdate8" + } + }, + "additionalProperties": false } ] }, @@ -869,6 +895,78 @@ }, "additionalProperties": false }, + "LibraryConfigUpdate7": { + "type": "object", + "properties": { + "input_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + }, + "lp_config": { + "anyOf": [ + { + "$ref": "#/definitions/LiquidityProviderConfig2" + }, + { + "type": "null" + } + ] + }, + "output_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "LibraryConfigUpdate8": { + "type": "object", + "properties": { + "input_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + }, + "lw_config": { + "anyOf": [ + { + "$ref": "#/definitions/LiquidityWithdrawerConfig2" + }, + { + "type": "null" + } + ] + }, + "output_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, "LibraryInfo": { "type": "object", "required": [ @@ -963,6 +1061,28 @@ }, "additionalProperties": false }, + "LiquidityProviderConfig2": { + "type": "object", + "required": [ + "pool_asset_1", + "pool_asset_2", + "pool_id" + ], + "properties": { + "pool_asset_1": { + "type": "string" + }, + "pool_asset_2": { + "type": "string" + }, + "pool_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, "LiquidityWithdrawerConfig": { "type": "object", "required": [ @@ -980,6 +1100,20 @@ }, "additionalProperties": false }, + "LiquidityWithdrawerConfig2": { + "type": "object", + "required": [ + "pool_id" + ], + "properties": { + "pool_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, "Message": { "type": "object", "required": [ @@ -1335,7 +1469,7 @@ "authorization_addr": "", "authorization_bridge_addrs": {}, "processor_addrs": {}, - "processor_bridge_addrs": {} + "processor_bridge_addrs": [] }, "allOf": [ { diff --git a/program-manager/src/program_config.rs b/program-manager/src/program_config.rs index a32e5ccf..f2dafddc 100644 --- a/program-manager/src/program_config.rs +++ b/program-manager/src/program_config.rs @@ -43,8 +43,6 @@ pub struct AuthorizationData { /// Key: domain name | Value: authorization bridge address on that domain pub authorization_bridge_addrs: BTreeMap, /// List of processor bridge addresses by domain - /// All addresses are on nuetron, mapping to what domain this bridge account is for - /// Key: domain name | Value: processor bridge address on that domain pub processor_bridge_addrs: Vec, } @@ -165,7 +163,8 @@ impl ProgramConfig { .get(domain.get_chain_name()) .map( |chain_info| valence_processor_utils::msg::PolytoneContracts { - polytone_proxy_address: authorization_bridge_account_addr.clone(), + polytone_proxy_address: authorization_bridge_account_addr + .to_string(), polytone_note_address: chain_info.note_addr.to_string(), timeout_seconds: 3_010_000, }, @@ -187,19 +186,14 @@ impl ProgramConfig { .instantiate_processor( self.id, salt, - // TODO: should this really be authorization addr? - authorization_bridge_account_addr.clone(), - authorization_addr.clone(), + authorization_bridge_account_addr.to_string(), + authorization_addr.to_string(), polytone_config, ) .await?; // construct and add the `ExternalDomain` info to the authorization contract // Adding external domain to the authorization contract will create the bridge account on that domain - println!( - "adding external domain chain name: {:?}", - domain.get_chain_name() - ); neutron_connector .add_external_domain( neutron_domain.get_chain_name(), From e365d40f183d1cd9449513296c6d214801f5312a Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 13:37:51 +0100 Subject: [PATCH 25/92] final cleanup --- local-interchaintest/examples/osmo_gamm.rs | 493 ++---------------- .../src/utils/authorization.rs | 80 ++- local-interchaintest/src/utils/osmosis.rs | 53 +- local-interchaintest/src/utils/polytone.rs | 229 ++++++++ local-interchaintest/src/utils/processor.rs | 30 ++ 5 files changed, 441 insertions(+), 444 deletions(-) diff --git a/local-interchaintest/examples/osmo_gamm.rs b/local-interchaintest/examples/osmo_gamm.rs index 63358bb6..ff40c1db 100644 --- a/local-interchaintest/examples/osmo_gamm.rs +++ b/local-interchaintest/examples/osmo_gamm.rs @@ -1,42 +1,33 @@ -use std::{collections::HashMap, error::Error, time::Duration}; +use std::{error::Error, time::Duration}; use cosmwasm_std::Binary; -use cosmwasm_std_old::Uint64; use local_interchaintest::utils::{ + authorization::confirm_authorizations_callback_state, manager::{ - get_global_config, setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, - OSMOSIS_GAMM_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + setup_manager, use_manager_init, OSMOSIS_GAMM_LPER_NAME, OSMOSIS_GAMM_LWER_NAME, + POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - processor::get_processor_queue_items, + osmosis::gamm::setup_gamm_pool, + polytone::setup_polytone, + processor::confirm_remote_domain_processor_queue_length, GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; -use localic_std::{ - modules::{ - bank, - cosmwasm::{contract_execute, contract_query, CosmWasm}, - }, - relayer::Relayer, -}; +use localic_std::modules::{bank, cosmwasm::contract_execute}; use localic_utils::{ - utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, - GAIA_CHAIN_NAME, LOCAL_IC_API_URL, NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, - NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_DENOM, - OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, + ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; -use serde_json::Value; use valence_authorization_utils::{ - authorization::Priority, authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, - callback::ProcessorCallbackInfo, domain::Domain, msg::ProcessorMessage, }; use valence_program_manager::{ account::{AccountInfo, AccountType}, - bridge::{Bridge, PolytoneSingleChainInfo}, library::{LibraryConfig, LibraryInfo}, program_config_builder::ProgramConfigBuilder, }; @@ -125,13 +116,13 @@ fn main() -> Result<(), Box> { let gamm_lper_library = builder.add_library(LibraryInfo::new( "test_gamm_lp".to_string(), &osmo_domain, - LibraryConfig::ValenceOsmosisGammLper(gamm_lper_config.clone()), + LibraryConfig::ValenceOsmosisGammLper(gamm_lper_config), )); let gamm_lwer_library = builder.add_library(LibraryInfo::new( "test_gamm_lw".to_string(), &osmo_domain, - LibraryConfig::ValenceOsmosisGammWithdrawer(gamm_lwer_config.clone()), + LibraryConfig::ValenceOsmosisGammWithdrawer(gamm_lwer_config), )); // establish the input_acc -> lper_lib -> output_acc link @@ -194,10 +185,19 @@ fn main() -> Result<(), Box> { let mut program_config = builder.build(); - setup_polytone(&mut test_ctx)?; + // prior to initializing the manager, we do the middleware plumbing + setup_polytone( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_NAME, + NEUTRON_CHAIN_ID, + OSMOSIS_CHAIN_ID, + NEUTRON_CHAIN_DENOM, + OSMOSIS_CHAIN_DENOM, + )?; + info!("initializing manager..."); use_manager_init(&mut program_config)?; - info!("manager initialized successfully!"); let input_acc_addr = program_config .get_account(gamm_input_acc)? @@ -262,8 +262,7 @@ fn main() -> Result<(), Box> { denom: OSMOSIS_CHAIN_DENOM.to_string(), amount: 1_000_000u128.into(), }, - ) - .unwrap(); + )?; std::thread::sleep(Duration::from_secs(3)); @@ -290,16 +289,13 @@ fn main() -> Result<(), Box> { info!("ntrn processor contract address: {ntrn_processor_contract_address}"); let lp_message = ProcessorMessage::CosmwasmExecuteMsg { - msg: Binary::from( - serde_json::to_vec( - &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( - valence_osmosis_gamm_lper::msg::FunctionMsgs::ProvideDoubleSidedLiquidity { - expected_spot_price: None, - }, - ), - ) - .unwrap(), - ), + msg: Binary::from(serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_gamm_lper::msg::FunctionMsgs::ProvideDoubleSidedLiquidity { + expected_spot_price: None, + }, + ), + )?), }; let provide_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { @@ -309,20 +305,17 @@ fn main() -> Result<(), Box> { }, ); - let enqueue_resp = contract_execute( + contract_execute( test_ctx .get_request_builder() .get_request_builder(NEUTRON_CHAIN_NAME), &authorization_contract_address, DEFAULT_KEY, - &serde_json::to_string(&provide_liquidity_msg).unwrap(), + &serde_json::to_string(&provide_liquidity_msg)?, GAS_FLAGS, - ) - .unwrap(); - info!("enqueue authorizations response: {:?}", enqueue_resp); - - info!("provide_liquidity_msg sent to the authorization contract!"); + )?; + info!("confirming that osmosis processor enqueued the provide_liquidity_msg..."); confirm_remote_domain_processor_queue_length( &mut test_ctx, OSMOSIS_CHAIN_NAME, @@ -331,7 +324,7 @@ fn main() -> Result<(), Box> { ); info!("Ticking osmo processor..."); - let resp = contract_execute( + contract_execute( test_ctx .get_request_builder() .get_request_builder(OSMOSIS_CHAIN_NAME), @@ -341,15 +334,12 @@ fn main() -> Result<(), Box> { &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( valence_processor_utils::msg::PermissionlessMsg::Tick {}, ), - ) - .unwrap(), + )?, &format!( "--gas=auto --gas-adjustment=3.0 --fees {}{}", 5_000_000, OSMOSIS_CHAIN_DENOM ), - ) - .unwrap(); - info!("osmo processor tick response: {:?}", resp); + )?; std::thread::sleep(std::time::Duration::from_secs(3)); @@ -373,25 +363,20 @@ fn main() -> Result<(), Box> { assert_eq!(output_acc_bal.len(), 1); assert_eq!(output_acc_bal[0].denom, "gamm/pool/1".to_string()); - info!("confirmed liquidity provision!"); - info!("asserting authorizations callbacks state sync..."); - + info!("confirmed liquidity provision! asserting authorizations callbacks state sync..."); confirm_authorizations_callback_state( &mut test_ctx, NEUTRON_CHAIN_NAME, &authorization_contract_address, 0, - ); + )?; let lw_message = ProcessorMessage::CosmwasmExecuteMsg { - msg: Binary::from( - serde_json::to_vec( - &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( - valence_osmosis_gamm_withdrawer::msg::FunctionMsgs::WithdrawLiquidity {}, - ), - ) - .unwrap(), - ), + msg: Binary::from(serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_gamm_withdrawer::msg::FunctionMsgs::WithdrawLiquidity {}, + ), + )?), }; let withdraw_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { @@ -407,13 +392,11 @@ fn main() -> Result<(), Box> { .get_request_builder(NEUTRON_CHAIN_NAME), &authorization_contract_address, DEFAULT_KEY, - &serde_json::to_string(&withdraw_liquidity_msg).unwrap(), + &serde_json::to_string(&withdraw_liquidity_msg)?, GAS_FLAGS, - ) - .unwrap(); - - info!("withdraw_liquidity_msg sent to the authorization contract!"); + )?; + info!("confirming that osmosis processor enqueued the withdraw_liquidity_msg..."); confirm_remote_domain_processor_queue_length( &mut test_ctx, OSMOSIS_CHAIN_NAME, @@ -422,7 +405,7 @@ fn main() -> Result<(), Box> { ); info!("Ticking osmo processor..."); - let resp = contract_execute( + contract_execute( test_ctx .get_request_builder() .get_request_builder(OSMOSIS_CHAIN_NAME), @@ -432,15 +415,12 @@ fn main() -> Result<(), Box> { &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( valence_processor_utils::msg::PermissionlessMsg::Tick {}, ), - ) - .unwrap(), + )?, &format!( "--gas=auto --gas-adjustment=3.0 --fees {}{}", 5_000_000, OSMOSIS_CHAIN_DENOM ), - ) - .unwrap(); - info!("osmo processor tick response: {:?}", resp); + )?; std::thread::sleep(std::time::Duration::from_secs(3)); @@ -464,379 +444,12 @@ fn main() -> Result<(), Box> { assert_eq!(final_acc_bal.len(), 2); info!("asserting authorizations callbacks state sync..."); - confirm_authorizations_callback_state( &mut test_ctx, NEUTRON_CHAIN_NAME, &authorization_contract_address, 1, - ); - - Ok(()) -} - -fn setup_polytone(test_ctx: &mut TestContext) -> Result<(), Box> { - // Before setting up the external domains and the processor on the external domain, we are going to set up polytone and predict the proxy addresses on both sides - let mut polytone_note_on_neutron = test_ctx - .get_contract() - .contract(POLYTONE_NOTE_NAME) - .get_cw(); - - let mut polytone_voice_on_neutron = test_ctx - .get_contract() - .contract(POLYTONE_VOICE_NAME) - .get_cw(); - - let polytone_proxy_on_neutron = test_ctx - .get_contract() - .contract(POLYTONE_PROXY_NAME) - .get_cw(); - - let mut polytone_note_on_osmosis = test_ctx - .get_contract() - .src(OSMOSIS_CHAIN_NAME) - .contract(POLYTONE_NOTE_NAME) - .get_cw(); - - let mut polytone_voice_on_osmosis = test_ctx - .get_contract() - .src(OSMOSIS_CHAIN_NAME) - .contract(POLYTONE_VOICE_NAME) - .get_cw(); - - let polytone_proxy_on_osmosis = test_ctx - .get_contract() - .src(OSMOSIS_CHAIN_NAME) - .contract(POLYTONE_PROXY_NAME) - .get_cw(); - - let polytone_note_instantiate_msg = polytone_note::msg::InstantiateMsg { - pair: None, - block_max_gas: Uint64::new(3010000), - }; - - let neutron_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { - proxy_code_id: Uint64::new(polytone_proxy_on_neutron.code_id.unwrap()), - block_max_gas: Uint64::new(3010000), - contract_addr_len: None, - }; - - let osmo_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { - proxy_code_id: Uint64::new(polytone_proxy_on_osmosis.code_id.unwrap()), - block_max_gas: Uint64::new(3010000), - contract_addr_len: None, - }; - - info!("Instantiating polytone contracts on both domains"); - let polytone_note_on_neutron_address = polytone_note_on_neutron - .instantiate( - DEFAULT_KEY, - &serde_json::to_string(&polytone_note_instantiate_msg).unwrap(), - "polytone-note-neutron", - None, - "", - ) - .unwrap() - .address; - - info!("Polytone Note on Neutron: {polytone_note_on_neutron_address}"); - std::thread::sleep(std::time::Duration::from_secs(2)); - - let polytone_voice_on_neutron_address = polytone_voice_on_neutron - .instantiate( - DEFAULT_KEY, - &serde_json::to_string(&neutron_polytone_voice_instantiate_msg).unwrap(), - "polytone-voice-neutron", - None, - "", - ) - .unwrap() - .address; - - info!("Polytone voice on neutron: {polytone_voice_on_neutron_address}",); - std::thread::sleep(std::time::Duration::from_secs(2)); - - let polytone_note_on_osmo_address = polytone_note_on_osmosis - .instantiate( - DEFAULT_KEY, - &serde_json::to_string(&polytone_note_instantiate_msg).unwrap(), - "polytone-note-osmosis", - None, - &format!("--fees {}{}", 5000, OSMOSIS_CHAIN_DENOM), - ) - .unwrap() - .address; - - info!("polytone note on osmosis: {polytone_note_on_osmo_address}"); - std::thread::sleep(std::time::Duration::from_secs(2)); - - let polytone_voice_on_osmo_address = polytone_voice_on_osmosis - .instantiate( - DEFAULT_KEY, - &serde_json::to_string(&osmo_polytone_voice_instantiate_msg).unwrap(), - "polytone-voice-osmosis", - None, - &format!("--fees {}{}", 5000, OSMOSIS_CHAIN_DENOM), - ) - .unwrap() - .address; - info!("Polytone Voice on osmo: {polytone_voice_on_osmo_address}"); - - std::thread::sleep(std::time::Duration::from_secs(2)); - info!("Creating WASM connections..."); - - let relayer = Relayer::new( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - ); - - polytone_note_on_neutron - .create_wasm_connection( - &relayer, - "neutron-osmosis", - &CosmWasm::new_from_existing( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - None, - None, - Some(polytone_voice_on_osmo_address.clone()), - ), - "unordered", - "polytone-1", - ) - .unwrap(); - - polytone_voice_on_neutron - .create_wasm_connection( - &relayer, - "neutron-osmosis", - &CosmWasm::new_from_existing( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - None, - None, - Some(polytone_note_on_osmo_address.clone()), - ), - "unordered", - "polytone-1", - ) - .unwrap(); - - // Give some time to make sure the channels are open - std::thread::sleep(Duration::from_secs(15)); - - // Get the connection ids so that we can predict the proxy addresses - let neutron_channels = relayer.get_channels(NEUTRON_CHAIN_ID).unwrap(); - - let neutron_to_osmo_polytone_channel = neutron_channels - .iter() - .find_map(|neutron_channel| { - if neutron_channel.port_id - == format!("wasm.{}", polytone_note_on_neutron_address.clone()) - { - Some(neutron_channel.clone()) - } else { - None - } - }) - .unwrap(); - - let osmo_channels = relayer.get_channels(OSMOSIS_CHAIN_ID).unwrap(); - - let osmo_to_neutron_polytone_channel = osmo_channels - .iter() - .find_map(|osmo_channel| { - if osmo_channel.port_id == format!("wasm.{}", polytone_note_on_osmo_address.clone()) { - Some(osmo_channel.clone()) - } else { - None - } - }) - .unwrap(); - - let osmo_polytone_info = PolytoneSingleChainInfo { - voice_addr: polytone_voice_on_osmo_address, - note_addr: polytone_note_on_osmo_address, - other_note_port: neutron_to_osmo_polytone_channel.port_id, - connection_id: osmo_to_neutron_polytone_channel - .connection_hops - .first() - .cloned() - .unwrap(), - channel_id: osmo_to_neutron_polytone_channel.channel_id, - }; - let neutron_polytone_info = PolytoneSingleChainInfo { - voice_addr: polytone_voice_on_neutron_address, - note_addr: polytone_note_on_neutron_address, - other_note_port: osmo_to_neutron_polytone_channel.port_id, - connection_id: neutron_to_osmo_polytone_channel - .connection_hops - .first() - .cloned() - .unwrap(), - channel_id: neutron_to_osmo_polytone_channel.channel_id, - }; - - let osmo_to_neutron_polytone_bridge_info: HashMap = - HashMap::from([ - (NEUTRON_CHAIN_NAME.to_string(), neutron_polytone_info), - (OSMOSIS_CHAIN_NAME.to_string(), osmo_polytone_info), - ]); - - let mut neutron_bridge_map: HashMap = HashMap::new(); - neutron_bridge_map.insert( - OSMOSIS_CHAIN_NAME.to_string(), - Bridge::Polytone(osmo_to_neutron_polytone_bridge_info), - ); - - let mut gc = get_global_config(); - - gc.bridges - .insert(NEUTRON_CHAIN_NAME.to_string(), neutron_bridge_map); + )?; Ok(()) } - -fn setup_gamm_pool( - test_ctx: &mut TestContext, - denom_1: &str, - denom_2: &str, -) -> Result> { - info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); - test_ctx - .build_tx_transfer() - .with_chain_name(NEUTRON_CHAIN_NAME) - .with_amount(1_000_000_000u128) - .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) - .with_denom(NEUTRON_CHAIN_DENOM) - .send() - .unwrap(); - std::thread::sleep(std::time::Duration::from_secs(3)); - - let token_balances = bank::get_balance( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - OSMOSIS_CHAIN_ADMIN_ADDR, - ); - info!("osmosis chain admin addr balances: {:?}", token_balances); - - test_ctx - .build_tx_create_osmo_pool() - .with_weight(denom_1, 1) - .with_weight(denom_2, 1) - .with_initial_deposit(denom_1, 100_000_000) - .with_initial_deposit(denom_2, 100_000_000) - .send()?; - - // Get its id - let pool_id = test_ctx - .get_osmo_pool() - .denoms(denom_1.into(), denom_2.to_string()) - .get_u64(); - - info!("Gamm pool id: {:?}", pool_id); - - Ok(pool_id) -} - -fn confirm_remote_domain_processor_queue_length( - test_ctx: &mut TestContext, - processor_domain: &str, - processor_addr: &str, - len: usize, -) { - let mut tries = 0; - loop { - let items = - get_processor_queue_items(test_ctx, processor_domain, processor_addr, Priority::Medium); - info!( - "{processor_domain} processor queue (len {:?}): {:?}", - items.len(), - items - ); - - if items.len() == len { - break; - } else if tries > 10 { - panic!("Batch not found after 10 tries"); - } - - tries += 1; - std::thread::sleep(std::time::Duration::from_secs(5)); - } -} - -fn confirm_authorizations_callback_state( - test_ctx: &mut TestContext, - authorization_domain: &str, - authorization_addr: &str, - execution_id: u64, -) { - let mut tries = 0; - loop { - let query_processor_callbacks_response: Value = serde_json::from_value( - contract_query( - test_ctx - .get_request_builder() - .get_request_builder(authorization_domain), - authorization_addr, - &serde_json::to_string( - &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { - start_after: None, - limit: None, - }, - ) - .unwrap(), - )["data"] - .clone(), - ) - .unwrap(); - - info!( - "{authorization_domain} authorization mod processor callbacks: {:?}", - query_processor_callbacks_response - ); - - if query_processor_callbacks_response.is_null() { - info!("No authorization callbacks not found yet..."); - } else { - let processor_callback_infos: Vec = - serde_json::from_value(query_processor_callbacks_response).unwrap(); - - let callback_by_id = processor_callback_infos - .iter() - .find(|x| x.execution_id == execution_id); - - info!( - "processor callback #{execution_id} info: {:?}", - callback_by_id - ); - - if let Some(cb) = callback_by_id { - match cb.execution_result { - valence_authorization_utils::callback::ExecutionResult::Success => { - info!("callback #{execution_id} execution = success!"); - break; - } - _ => { - info!( - "callback #{execution_id} execution result: {:?}", - cb.execution_result - ); - } - } - } - } - - tries += 1; - if tries == 10 { - panic!("Batch not found after 10 tries"); - } else { - std::thread::sleep(std::time::Duration::from_secs(5)); - } - } -} diff --git a/local-interchaintest/src/utils/authorization.rs b/local-interchaintest/src/utils/authorization.rs index 23043306..1939b020 100644 --- a/local-interchaintest/src/utils/authorization.rs +++ b/local-interchaintest/src/utils/authorization.rs @@ -2,7 +2,7 @@ use std::{env, error::Error, time::Duration}; use cosmwasm_std_old::Uint64; use localic_std::{ - modules::cosmwasm::{contract_execute, contract_instantiate, CosmWasm}, + modules::cosmwasm::{contract_execute, contract_instantiate, contract_query, CosmWasm}, relayer::Relayer, }; use localic_utils::{ @@ -10,8 +10,10 @@ use localic_utils::{ NEUTRON_CHAIN_NAME, }; use log::info; -use valence_authorization_utils::msg::{ - CallbackProxy, Connector, ExternalDomainInfo, PermissionedMsg, +use serde_json::Value; +use valence_authorization_utils::{ + callback::ProcessorCallbackInfo, + msg::{CallbackProxy, Connector, ExternalDomainInfo, PermissionedMsg}, }; use valence_processor_utils::msg::PolytoneContracts; @@ -459,3 +461,75 @@ pub fn set_up_external_domain_with_polytone( Ok(predicted_processor_on_external_domain_address) } + +/// queries the authorization contract processor callbacks and tries to confirm that +/// the processor callback with `execution_id` execution_result is `Success`. +/// retries for 10 times with a 5 second sleep in between. fails after 10 retries. +pub fn confirm_authorizations_callback_state( + test_ctx: &mut TestContext, + authorization_domain: &str, + authorization_addr: &str, + execution_id: u64, +) -> Result<(), Box> { + let mut tries = 0; + loop { + let query_processor_callbacks_response: Value = serde_json::from_value( + contract_query( + test_ctx + .get_request_builder() + .get_request_builder(authorization_domain), + authorization_addr, + &serde_json::to_string( + &valence_authorization_utils::msg::QueryMsg::ProcessorCallbacks { + start_after: None, + limit: None, + }, + )?, + )["data"] + .clone(), + )?; + + info!( + "{authorization_domain} authorization mod processor callbacks: {:?}", + query_processor_callbacks_response + ); + + if query_processor_callbacks_response.is_null() { + info!("No authorization callbacks not found yet..."); + } else { + let processor_callback_infos: Vec = + serde_json::from_value(query_processor_callbacks_response)?; + + let callback_by_id = processor_callback_infos + .iter() + .find(|x| x.execution_id == execution_id); + + info!( + "processor callback #{execution_id} info: {:?}", + callback_by_id + ); + + if let Some(cb) = callback_by_id { + match cb.execution_result { + valence_authorization_utils::callback::ExecutionResult::Success => { + info!("callback #{execution_id} execution = success!"); + return Ok(()); + } + _ => { + info!( + "callback #{execution_id} execution result: {:?}", + cb.execution_result + ); + } + } + } + } + + tries += 1; + if tries == 10 { + return Err("Batch not found after 10 tries".into()); + } else { + std::thread::sleep(std::time::Duration::from_secs(5)); + } + } +} diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs index f1b6c441..a8f88988 100644 --- a/local-interchaintest/src/utils/osmosis.rs +++ b/local-interchaintest/src/utils/osmosis.rs @@ -1 +1,52 @@ -pub mod gamm {} +pub mod gamm { + use std::error::Error; + + use localic_std::modules::bank; + use localic_utils::{ + utils::test_context::TestContext, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_NAME, + }; + use log::info; + + pub fn setup_gamm_pool( + test_ctx: &mut TestContext, + denom_1: &str, + denom_2: &str, + ) -> Result> { + info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); + test_ctx + .build_tx_transfer() + .with_chain_name(NEUTRON_CHAIN_NAME) + .with_amount(1_000_000_000u128) + .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) + .with_denom(NEUTRON_CHAIN_DENOM) + .send()?; + std::thread::sleep(std::time::Duration::from_secs(3)); + + let token_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + OSMOSIS_CHAIN_ADMIN_ADDR, + ); + info!("osmosis chain admin addr balances: {:?}", token_balances); + + test_ctx + .build_tx_create_osmo_pool() + .with_weight(denom_1, 1) + .with_weight(denom_2, 1) + .with_initial_deposit(denom_1, 100_000_000) + .with_initial_deposit(denom_2, 100_000_000) + .send()?; + + // Get its id + let pool_id = test_ctx + .get_osmo_pool() + .denoms(denom_1.into(), denom_2.to_string()) + .get_u64(); + + info!("Gamm pool id: {:?}", pool_id); + + Ok(pool_id) + } +} diff --git a/local-interchaintest/src/utils/polytone.rs b/local-interchaintest/src/utils/polytone.rs index d2087cc7..571d6776 100644 --- a/local-interchaintest/src/utils/polytone.rs +++ b/local-interchaintest/src/utils/polytone.rs @@ -1,4 +1,15 @@ +use std::{collections::HashMap, error::Error, time::Duration}; + +use cosmwasm_std_old::Uint64; +use localic_std::{modules::cosmwasm::CosmWasm, relayer::Relayer}; +use localic_utils::{utils::test_context::TestContext, DEFAULT_KEY}; +use log::info; use sha2::{Digest, Sha512}; +use valence_program_manager::bridge::{Bridge, PolytoneSingleChainInfo}; + +use crate::utils::manager::{ + get_global_config, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, +}; pub fn salt_for_proxy( connection_id: &str, @@ -12,3 +23,221 @@ pub fn salt_for_proxy( .finalize() .to_vec() } + +/// performs the plumbing needed to establish a relayer polytone connection +/// between two domains +pub fn setup_polytone( + test_ctx: &mut TestContext, + domain_1: &str, + domain_2: &str, + domain_1_id: &str, + domain_2_id: &str, + domain_1_denom: &str, + domain_2_denom: &str, +) -> Result<(), Box> { + let mut polytone_note_on_domain_1 = test_ctx + .get_contract() + .src(domain_1) + .contract(POLYTONE_NOTE_NAME) + .get_cw(); + + let mut polytone_voice_on_domain_1 = test_ctx + .get_contract() + .src(domain_1) + .contract(POLYTONE_VOICE_NAME) + .get_cw(); + + let polytone_proxy_on_domain_1 = test_ctx + .get_contract() + .src(domain_1) + .contract(POLYTONE_PROXY_NAME) + .get_cw(); + + let mut polytone_note_on_domain_2 = test_ctx + .get_contract() + .src(domain_2) + .contract(POLYTONE_NOTE_NAME) + .get_cw(); + + let mut polytone_voice_on_domain_2 = test_ctx + .get_contract() + .src(domain_2) + .contract(POLYTONE_VOICE_NAME) + .get_cw(); + + let polytone_proxy_on_domain_2 = test_ctx + .get_contract() + .src(domain_2) + .contract(POLYTONE_PROXY_NAME) + .get_cw(); + + let polytone_note_instantiate_msg = polytone_note::msg::InstantiateMsg { + pair: None, + block_max_gas: Uint64::new(3010000), + }; + + let domain_1_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { + proxy_code_id: Uint64::new(polytone_proxy_on_domain_1.code_id.unwrap()), + block_max_gas: Uint64::new(3010000), + contract_addr_len: None, + }; + + let domain_2_polytone_voice_instantiate_msg = polytone_voice::msg::InstantiateMsg { + proxy_code_id: Uint64::new(polytone_proxy_on_domain_2.code_id.unwrap()), + block_max_gas: Uint64::new(3010000), + contract_addr_len: None, + }; + + info!("Instantiating polytone contracts on both domains"); + let polytone_note_on_domain_1_address = polytone_note_on_domain_1 + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&polytone_note_instantiate_msg)?, + &format!("polytone-note-{domain_1}"), + None, + &format!("--fees {}{}", 5000, domain_1_denom), + )? + .address; + + info!("Polytone note on {domain_1}: {polytone_note_on_domain_1_address}"); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_voice_on_domain_1_address = polytone_voice_on_domain_1 + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&domain_1_polytone_voice_instantiate_msg)?, + &format!("polytone-voice-{domain_1}"), + None, + &format!("--fees {}{}", 5000, domain_1_denom), + )? + .address; + + info!("Polytone voice on {domain_1}: {polytone_voice_on_domain_1_address}",); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_note_on_domain_2_address = polytone_note_on_domain_2 + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&polytone_note_instantiate_msg)?, + &format!("polytone-note-{domain_2}"), + None, + &format!("--fees {}{}", 5000, domain_2_denom), + )? + .address; + + info!("polytone note on {domain_2}: {polytone_note_on_domain_2_address}"); + std::thread::sleep(std::time::Duration::from_secs(2)); + + let polytone_voice_on_domain_2_address = polytone_voice_on_domain_2 + .instantiate( + DEFAULT_KEY, + &serde_json::to_string(&domain_2_polytone_voice_instantiate_msg)?, + &format!("polytone-voice-{domain_2}"), + None, + &format!("--fees {}{}", 5000, domain_2_denom), + )? + .address; + info!("Polytone voice on {domain_2}: {polytone_voice_on_domain_2_address}"); + + std::thread::sleep(std::time::Duration::from_secs(2)); + info!("Creating WASM connections..."); + + let relayer = Relayer::new(test_ctx.get_request_builder().get_request_builder(domain_1)); + + polytone_note_on_domain_1.create_wasm_connection( + &relayer, + &format!("{domain_1}-{domain_2}"), + &CosmWasm::new_from_existing( + test_ctx.get_request_builder().get_request_builder(domain_2), + None, + None, + Some(polytone_voice_on_domain_2_address.to_string()), + ), + "unordered", + "polytone-1", + )?; + + polytone_voice_on_domain_1.create_wasm_connection( + &relayer, + &format!("{domain_1}-{domain_2}"), + &CosmWasm::new_from_existing( + test_ctx.get_request_builder().get_request_builder(domain_2), + None, + None, + Some(polytone_note_on_domain_2_address.to_string()), + ), + "unordered", + "polytone-1", + )?; + + // Give some time to make sure the channels are open + std::thread::sleep(Duration::from_secs(15)); + + // Get the connection ids so that we can predict the proxy addresses + let domain_1_channels = relayer.get_channels(domain_1_id)?; + + let domain_1_to_domain_2_polytone_channel = domain_1_channels + .iter() + .find_map(|domain_1| { + if domain_1.port_id == format!("wasm.{}", polytone_note_on_domain_1_address) { + Some(domain_1.clone()) + } else { + None + } + }) + .unwrap(); + + let domain_2_channels = relayer.get_channels(domain_2_id)?; + + let domain_2_to_domain_1_polytone_channel = domain_2_channels + .iter() + .find_map(|domain_2_channel| { + if domain_2_channel.port_id == format!("wasm.{}", polytone_note_on_domain_2_address) { + Some(domain_2_channel.clone()) + } else { + None + } + }) + .unwrap(); + + let domain_2_polytone_info = PolytoneSingleChainInfo { + voice_addr: polytone_voice_on_domain_2_address, + note_addr: polytone_note_on_domain_2_address, + other_note_port: domain_1_to_domain_2_polytone_channel.port_id, + connection_id: domain_2_to_domain_1_polytone_channel + .connection_hops + .first() + .cloned() + .unwrap(), + channel_id: domain_2_to_domain_1_polytone_channel.channel_id, + }; + let domain_1_polytone_info = PolytoneSingleChainInfo { + voice_addr: polytone_voice_on_domain_1_address, + note_addr: polytone_note_on_domain_1_address, + other_note_port: domain_2_to_domain_1_polytone_channel.port_id, + connection_id: domain_1_to_domain_2_polytone_channel + .connection_hops + .first() + .cloned() + .unwrap(), + channel_id: domain_1_to_domain_2_polytone_channel.channel_id, + }; + + let domain_2_to_domain_1_polytone_bridge_info: HashMap = + HashMap::from([ + (domain_1.to_string(), domain_1_polytone_info), + (domain_2.to_string(), domain_2_polytone_info), + ]); + + let mut domain_1_bridge_map: HashMap = HashMap::new(); + domain_1_bridge_map.insert( + domain_2.to_string(), + Bridge::Polytone(domain_2_to_domain_1_polytone_bridge_info), + ); + + let mut gc = get_global_config(); + + gc.bridges.insert(domain_1.to_string(), domain_1_bridge_map); + + Ok(()) +} diff --git a/local-interchaintest/src/utils/processor.rs b/local-interchaintest/src/utils/processor.rs index 28b1cb59..b8e1735c 100644 --- a/local-interchaintest/src/utils/processor.rs +++ b/local-interchaintest/src/utils/processor.rs @@ -6,6 +6,36 @@ use valence_processor_utils::processor::MessageBatch; use super::GAS_FLAGS; +/// queries the remote domain processor queue and tries to confirm that the queue length +/// matches `len`. +/// retries for 10 times with a 5 second sleep in between. fails after 10 retries. +pub fn confirm_remote_domain_processor_queue_length( + test_ctx: &mut TestContext, + processor_domain: &str, + processor_addr: &str, + len: usize, +) { + let mut tries = 0; + loop { + let items = + get_processor_queue_items(test_ctx, processor_domain, processor_addr, Priority::Medium); + info!( + "{processor_domain} processor queue (len {:?}): {:?}", + items.len(), + items + ); + + if items.len() == len { + break; + } else if tries > 10 { + panic!("Batch not found after 10 tries"); + } + + tries += 1; + std::thread::sleep(std::time::Duration::from_secs(5)); + } +} + pub fn tick_processor( test_ctx: &mut TestContext, chain_name: &str, From b7404aff83fea1c88eb027ac0769371f3d15c1f7 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 14:00:34 +0100 Subject: [PATCH 26/92] init cl e2e test --- Cargo.lock | 1 + local-interchaintest/Cargo.toml | 1 + local-interchaintest/examples/osmo_cl.rs | 119 ++++++++++++++++++++++ local-interchaintest/src/utils/manager.rs | 2 + 4 files changed, 123 insertions(+) create mode 100644 local-interchaintest/examples/osmo_cl.rs diff --git a/Cargo.lock b/Cargo.lock index fec0d39d..a58421dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2585,6 +2585,7 @@ dependencies = [ "valence-osmosis-cl-withdrawer", "valence-osmosis-gamm-lper", "valence-osmosis-gamm-withdrawer", + "valence-osmosis-utils", "valence-processor", "valence-processor-utils", "valence-program-manager", diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index b2d73fb9..eb62bd8b 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -42,4 +42,5 @@ valence-osmosis-gamm-lper = { workspace = true } valence-osmosis-gamm-withdrawer = { workspace = true } valence-osmosis-cl-lper = { workspace = true } valence-osmosis-cl-withdrawer = { workspace = true } +valence-osmosis-utils = { workspace = true } tokio = { workspace = true } diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs new file mode 100644 index 00000000..b59b7018 --- /dev/null +++ b/local-interchaintest/examples/osmo_cl.rs @@ -0,0 +1,119 @@ +use std::{error::Error, time::Duration}; + +use cosmwasm_std::{Binary, Int64}; +use local_interchaintest::utils::{ + authorization::confirm_authorizations_callback_state, + manager::{ + setup_manager, use_manager_init, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, + POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + }, + polytone::setup_polytone, + processor::confirm_remote_domain_processor_queue_length, + GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, +}; + +use localic_std::modules::{bank, cosmwasm::contract_execute}; +use localic_utils::{ + ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, +}; +use log::info; +use valence_authorization_utils::{ + authorization_message::{Message, MessageDetails, MessageType}, + builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, + domain::Domain, + msg::ProcessorMessage, +}; +use valence_osmosis_utils::utils::cl_utils::TickRange; +use valence_program_manager::{ + account::{AccountInfo, AccountType}, + library::{LibraryConfig, LibraryInfo}, + program_config_builder::ProgramConfigBuilder, +}; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let mut test_ctx = TestContextBuilder::default() + .with_unwrap_raw_logs(true) + .with_api_url(LOCAL_IC_API_URL) + .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) + .with_chain(ConfigChainBuilder::default_neutron().build()?) + .with_chain(ConfigChainBuilder::default_osmosis().build()?) + .with_log_file_path(LOGS_FILE_PATH) + .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) + .build()?; + + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + // TODO + let pool_id = 1u64; + + setup_manager( + &mut test_ctx, + NEUTRON_OSMO_CONFIG_FILE, + vec![GAIA_CHAIN_NAME], + vec![ + OSMOSIS_CL_LPER_NAME, + OSMOSIS_CL_LWER_NAME, + POLYTONE_NOTE_NAME, + POLYTONE_VOICE_NAME, + POLYTONE_PROXY_NAME, + ], + )?; + + let mut builder = ProgramConfigBuilder::new(NEUTRON_CHAIN_ADMIN_ADDR.to_string()); + let osmo_domain = + valence_program_manager::domain::Domain::CosmosCosmwasm(OSMOSIS_CHAIN_NAME.to_string()); + let ntrn_domain = + valence_program_manager::domain::Domain::CosmosCosmwasm(NEUTRON_CHAIN_NAME.to_string()); + + let cl_input_acc_info = + AccountInfo::new("cl_input".to_string(), &osmo_domain, AccountType::default()); + let cl_output_acc_info = AccountInfo::new( + "cl_output".to_string(), + &osmo_domain, + AccountType::default(), + ); + let final_output_acc_info = AccountInfo::new( + "final_output".to_string(), + &osmo_domain, + AccountType::default(), + ); + + let cl_input_acc = builder.add_account(cl_input_acc_info); + let cl_output_acc = builder.add_account(cl_output_acc_info); + let final_output_acc = builder.add_account(final_output_acc_info); + + info!("cl input acc: {:?}", cl_input_acc); + info!("cl output acc: {:?}", cl_output_acc); + info!("final output acc: {:?}", final_output_acc); + + let cl_lper_config = valence_osmosis_cl_lper::msg::LibraryConfig { + input_addr: cl_input_acc.clone(), + output_addr: cl_output_acc.clone(), + lp_config: valence_osmosis_cl_lper::msg::LiquidityProviderConfig { + pool_id: pool_id.into(), + pool_asset_2: OSMOSIS_CHAIN_DENOM.to_string(), + pool_asset_1: ntrn_on_osmo_denom.to_string(), + global_tick_range: TickRange { + lower_tick: Int64::from(-1000), + upper_tick: Int64::from(1000), + }, + }, + }; + + let cl_lwer_config = valence_osmosis_cl_withdrawer::msg::LibraryConfig { + input_addr: cl_output_acc.clone(), + output_addr: final_output_acc.clone(), + pool_id: pool_id.into(), + }; + + Ok(()) +} diff --git a/local-interchaintest/src/utils/manager.rs b/local-interchaintest/src/utils/manager.rs index 774ddfe1..3536f0ee 100644 --- a/local-interchaintest/src/utils/manager.rs +++ b/local-interchaintest/src/utils/manager.rs @@ -30,6 +30,8 @@ pub const ASTROPORT_LPER_NAME: &str = "valence_astroport_lper"; pub const ASTROPORT_WITHDRAWER_NAME: &str = "valence_astroport_withdrawer"; pub const OSMOSIS_GAMM_LPER_NAME: &str = "valence_osmosis_gamm_lper"; pub const OSMOSIS_GAMM_LWER_NAME: &str = "valence_osmosis_gamm_withdrawer"; +pub const OSMOSIS_CL_LPER_NAME: &str = "valence_osmosis_cl_lper"; +pub const OSMOSIS_CL_LWER_NAME: &str = "valence_osmosis_cl_withdrawer"; pub const POLYTONE_NOTE_NAME: &str = "polytone_note"; pub const POLYTONE_VOICE_NAME: &str = "polytone_voice"; pub const POLYTONE_PROXY_NAME: &str = "polytone_proxy"; From 479f6c7e516364c7a3e54379e49601ac9e85ceac Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 14:04:52 +0100 Subject: [PATCH 27/92] update program manager library with osmo cl variants --- program-manager/src/library.rs | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/program-manager/src/library.rs b/program-manager/src/library.rs index 59538f41..f0f269a7 100644 --- a/program-manager/src/library.rs +++ b/program-manager/src/library.rs @@ -81,6 +81,8 @@ pub enum LibraryConfig { ValenceAstroportWithdrawer(valence_astroport_withdrawer::msg::LibraryConfig), ValenceOsmosisGammLper(valence_osmosis_gamm_lper::msg::LibraryConfig), ValenceOsmosisGammWithdrawer(valence_osmosis_gamm_withdrawer::msg::LibraryConfig), + ValenceOsmosisClLper(valence_osmosis_cl_lper::msg::LibraryConfig), + ValenceOsmosisClWithdrawer(valence_osmosis_cl_withdrawer::msg::LibraryConfig), } #[derive( @@ -106,6 +108,8 @@ pub enum LibraryConfigUpdate { ValenceAstroportWithdrawer(valence_astroport_withdrawer::msg::LibraryConfigUpdate), ValenceOsmosisGammLper(valence_osmosis_gamm_lper::msg::LibraryConfigUpdate), ValenceOsmosisGammWithdrawer(valence_osmosis_gamm_withdrawer::msg::LibraryConfigUpdate), + ValenceOsmosisClLper(valence_osmosis_cl_lper::msg::LibraryConfigUpdate), + ValenceOsmosisClWithdrawer(valence_osmosis_cl_withdrawer::msg::LibraryConfigUpdate), } impl LibraryConfigUpdate { @@ -168,6 +172,22 @@ impl LibraryConfigUpdate { new_config: library_config_update, }) } + LibraryConfigUpdate::ValenceOsmosisClLper(library_config_update) => { + to_json_binary(&valence_library_utils::msg::ExecuteMsg::< + Empty, + valence_osmosis_cl_lper::msg::LibraryConfigUpdate, + >::UpdateConfig { + new_config: library_config_update, + }) + } + LibraryConfigUpdate::ValenceOsmosisClWithdrawer(library_config_update) => { + to_json_binary(&valence_library_utils::msg::ExecuteMsg::< + Empty, + valence_osmosis_cl_withdrawer::msg::LibraryConfigUpdate, + >::UpdateConfig { + new_config: library_config_update, + }) + } } .map_err(LibraryError::CosmwasmStdError) } @@ -225,6 +245,18 @@ impl LibraryConfig { let json = serde_json::to_string(&config)?; let res = ac.replace_all(&json, &replace_with); + *config = serde_json::from_str(&res)?; + } + LibraryConfig::ValenceOsmosisClLper(ref mut config) => { + let json = serde_json::to_string(&config)?; + let res = ac.replace_all(&json, &replace_with); + + *config = serde_json::from_str(&res)?; + } + LibraryConfig::ValenceOsmosisClWithdrawer(ref mut config) => { + let json = serde_json::to_string(&config)?; + let res = ac.replace_all(&json, &replace_with); + *config = serde_json::from_str(&res)?; } } @@ -270,6 +302,16 @@ impl LibraryConfig { processor, config: config.clone(), }), + LibraryConfig::ValenceOsmosisClLper(config) => to_vec(&InstantiateMsg { + owner, + processor, + config: config.clone(), + }), + LibraryConfig::ValenceOsmosisClWithdrawer(config) => to_vec(&InstantiateMsg { + owner, + processor, + config: config.clone(), + }), } .map_err(LibraryError::SerdeJsonError) } @@ -305,6 +347,14 @@ impl LibraryConfig { config.pre_validate(api)?; Ok(()) } + LibraryConfig::ValenceOsmosisClLper(config) => { + config.pre_validate(api)?; + Ok(()) + } + LibraryConfig::ValenceOsmosisClWithdrawer(config) => { + config.pre_validate(api)?; + Ok(()) + } } } @@ -334,6 +384,12 @@ impl LibraryConfig { LibraryConfig::ValenceOsmosisGammWithdrawer(config) => { Self::find_account_ids(ac, serde_json::to_string(&config)?) } + LibraryConfig::ValenceOsmosisClLper(config) => { + Self::find_account_ids(ac, serde_json::to_string(&config)?) + } + LibraryConfig::ValenceOsmosisClWithdrawer(config) => { + Self::find_account_ids(ac, serde_json::to_string(&config)?) + } } } From 4c23aeb5c63973d22aa4b6517c422d65296a1962 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 16:42:03 +0100 Subject: [PATCH 28/92] alter osmo genesis to allow permissionless pool creation; creating CL pool helper method --- Cargo.lock | 1 + local-interchaintest/Cargo.toml | 1 + .../chains/neutron_osmosis.json | 4 + local-interchaintest/examples/osmo_cl.rs | 31 +++----- local-interchaintest/src/utils/osmosis.rs | 74 +++++++++++++++++++ 5 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a58421dd..5b22f0c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2563,6 +2563,7 @@ dependencies = [ "localic-std", "localic-utils", "log", + "osmosis-std", "persistence-std", "polytone-note", "polytone-voice", diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index eb62bd8b..65dc81d8 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -44,3 +44,4 @@ valence-osmosis-cl-lper = { workspace = true } valence-osmosis-cl-withdrawer = { workspace = true } valence-osmosis-utils = { workspace = true } tokio = { workspace = true } +osmosis-std = { workspace = true } diff --git a/local-interchaintest/chains/neutron_osmosis.json b/local-interchaintest/chains/neutron_osmosis.json index a570fdeb..a4a46b25 100644 --- a/local-interchaintest/chains/neutron_osmosis.json +++ b/local-interchaintest/chains/neutron_osmosis.json @@ -217,6 +217,10 @@ { "key": "app_state.gov.params.min_deposit.0.denom", "value": "uosmo" + }, + { + "key": "app_state.concentratedliquidity.params.is_permissionless_pool_creation_enabled", + "value": true } ], "accounts": [ diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs index b59b7018..9a047cde 100644 --- a/local-interchaintest/examples/osmo_cl.rs +++ b/local-interchaintest/examples/osmo_cl.rs @@ -1,34 +1,24 @@ -use std::{error::Error, time::Duration}; +use std::error::Error; -use cosmwasm_std::{Binary, Int64}; +use cosmwasm_std::Int64; use local_interchaintest::utils::{ - authorization::confirm_authorizations_callback_state, manager::{ - setup_manager, use_manager_init, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, - POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + setup_manager, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, POLYTONE_NOTE_NAME, + POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - polytone::setup_polytone, - processor::confirm_remote_domain_processor_queue_length, - GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, + osmosis::concentrated_liquidity::setup_cl_pool, + LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; -use localic_std::modules::{bank, cosmwasm::contract_execute}; use localic_utils::{ - ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, - NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, - OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, + ConfigChainBuilder, TestContextBuilder, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, + OSMOSIS_CHAIN_NAME, }; use log::info; -use valence_authorization_utils::{ - authorization_message::{Message, MessageDetails, MessageType}, - builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, - domain::Domain, - msg::ProcessorMessage, -}; use valence_osmosis_utils::utils::cl_utils::TickRange; use valence_program_manager::{ account::{AccountInfo, AccountType}, - library::{LibraryConfig, LibraryInfo}, program_config_builder::ProgramConfigBuilder, }; @@ -52,8 +42,7 @@ fn main() -> Result<(), Box> { .dest(OSMOSIS_CHAIN_NAME) .get(); - // TODO - let pool_id = 1u64; + let pool_id = setup_cl_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; setup_manager( &mut test_ctx, diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs index a8f88988..f0d199f1 100644 --- a/local-interchaintest/src/utils/osmosis.rs +++ b/local-interchaintest/src/utils/osmosis.rs @@ -50,3 +50,77 @@ pub mod gamm { Ok(pool_id) } } + +pub mod concentrated_liquidity { + use std::error::Error; + + use localic_std::modules::bank; + use localic_utils::{ + utils::test_context::TestContext, DEFAULT_KEY, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_NAME, + }; + use log::info; + use serde_json::Value; + + pub fn setup_cl_pool( + test_ctx: &mut TestContext, + denom_1: &str, + denom_2: &str, + ) -> Result> { + info!("transferring 1000 neutron tokens to osmo admin addr for pool creation..."); + test_ctx + .build_tx_transfer() + .with_chain_name(NEUTRON_CHAIN_NAME) + .with_amount(1_000_000_000u128) + .with_recipient(OSMOSIS_CHAIN_ADMIN_ADDR) + .with_denom(NEUTRON_CHAIN_DENOM) + .send()?; + std::thread::sleep(std::time::Duration::from_secs(3)); + + let token_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + OSMOSIS_CHAIN_ADMIN_ADDR, + ); + info!("osmosis chain admin addr balances: {:?}", token_balances); + + let osmo_rb = test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME); + + let tick_spacing = 1000; + let spread_factor = 0.0005; + + let cmd = format!( + "tx concentratedliquidity create-pool {denom_2} {denom_1} {tick_spacing} {spread_factor} --fees=5000uosmo --from={} --gas auto --gas-adjustment 1.3 --output=json", + DEFAULT_KEY + ); + info!("CL creation cmd: {cmd}"); + + let cl_creation_response_events = osmo_rb.tx(&cmd, true)?["events"].clone(); + + let pool_creation_response_event = cl_creation_response_events + .as_array() + .unwrap() + .iter() + .filter_map(|e| match e["attributes"].clone() { + serde_json::Value::Array(vec) => Some(vec), + _ => None, + }) + .flatten() + .find(|e| e["key"] == "pool_id") + .unwrap(); + + let pool_id_str = match pool_creation_response_event["value"].clone() { + serde_json::Value::String(n) => n.to_string(), + _ => panic!("pool_id not found in cl creation response"), + }; + + let pool_id: u64 = pool_id_str.parse().unwrap(); + + info!("CL pool id: {:?}", pool_id); + + Ok(pool_id) + } +} From ffe17c8eefd1ebcf812ef4deaa785031057fa0cb Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 20 Nov 2024 17:54:55 +0100 Subject: [PATCH 29/92] asserting that CL position was created and transferred to output acc --- local-interchaintest/examples/osmo_cl.rs | 279 +++++++++++++++++++++- local-interchaintest/src/utils/osmosis.rs | 40 +++- 2 files changed, 306 insertions(+), 13 deletions(-) diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs index 9a047cde..5bc941e0 100644 --- a/local-interchaintest/examples/osmo_cl.rs +++ b/local-interchaintest/examples/osmo_cl.rs @@ -1,24 +1,34 @@ -use std::error::Error; +use std::{error::Error, time::Duration}; -use cosmwasm_std::Int64; +use cosmwasm_std::{Binary, Int64, Uint64}; use local_interchaintest::utils::{ manager::{ - setup_manager, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, POLYTONE_NOTE_NAME, - POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, + setup_manager, use_manager_init, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, + POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, }, - osmosis::concentrated_liquidity::setup_cl_pool, - LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, + osmosis::concentrated_liquidity::{query_cl_position, setup_cl_pool}, + polytone::setup_polytone, + processor::confirm_remote_domain_processor_queue_length, + GAS_FLAGS, LOGS_FILE_PATH, NEUTRON_OSMO_CONFIG_FILE, VALENCE_ARTIFACTS_PATH, }; +use localic_std::modules::{bank, cosmwasm::contract_execute}; use localic_utils::{ - ConfigChainBuilder, TestContextBuilder, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, - NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, - OSMOSIS_CHAIN_NAME, + ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, GAIA_CHAIN_NAME, LOCAL_IC_API_URL, + NEUTRON_CHAIN_ADMIN_ADDR, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_ID, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_ID, OSMOSIS_CHAIN_NAME, }; use log::info; +use valence_authorization_utils::{ + authorization_message::{Message, MessageDetails, MessageType}, + builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, + domain::Domain, + msg::ProcessorMessage, +}; use valence_osmosis_utils::utils::cl_utils::TickRange; use valence_program_manager::{ account::{AccountInfo, AccountType}, + library::{LibraryConfig, LibraryInfo}, program_config_builder::ProgramConfigBuilder, }; @@ -89,11 +99,11 @@ fn main() -> Result<(), Box> { output_addr: cl_output_acc.clone(), lp_config: valence_osmosis_cl_lper::msg::LiquidityProviderConfig { pool_id: pool_id.into(), - pool_asset_2: OSMOSIS_CHAIN_DENOM.to_string(), pool_asset_1: ntrn_on_osmo_denom.to_string(), + pool_asset_2: OSMOSIS_CHAIN_DENOM.to_string(), global_tick_range: TickRange { - lower_tick: Int64::from(-1000), - upper_tick: Int64::from(1000), + lower_tick: Int64::from(-10_000), + upper_tick: Int64::from(10_000), }, }, }; @@ -104,5 +114,250 @@ fn main() -> Result<(), Box> { pool_id: pool_id.into(), }; + let cl_lper_library = builder.add_library(LibraryInfo::new( + "test_cl_lper".to_string(), + &osmo_domain, + LibraryConfig::ValenceOsmosisClLper(cl_lper_config), + )); + + let cl_lwer_library = builder.add_library(LibraryInfo::new( + "test_cl_lwer".to_string(), + &osmo_domain, + LibraryConfig::ValenceOsmosisClWithdrawer(cl_lwer_config), + )); + + // establish the input_acc -> lper_lib -> output_acc link + builder.add_link(&cl_lper_library, vec![&cl_input_acc], vec![&cl_output_acc]); + // establish the output_acc -> lwer_lib -> final_output_acc link + builder.add_link( + &cl_lwer_library, + vec![&cl_output_acc], + vec![&final_output_acc], + ); + + let cl_lper_function = AtomicFunctionBuilder::new() + .with_domain(Domain::External(OSMOSIS_CHAIN_NAME.to_string())) + .with_contract_address(cl_lper_library.clone()) + .with_message_details(MessageDetails { + message_type: MessageType::CosmwasmExecuteMsg, + message: Message { + name: "process_function".to_string(), + params_restrictions: None, + }, + }) + .build(); + + let cl_lwer_function = AtomicFunctionBuilder::new() + .with_domain(Domain::External(OSMOSIS_CHAIN_NAME.to_string())) + .with_contract_address(cl_lwer_library.clone()) + .with_message_details(MessageDetails { + message_type: MessageType::CosmwasmExecuteMsg, + message: Message { + name: "process_function".to_string(), + params_restrictions: None, + }, + }) + .build(); + + builder.add_authorization( + AuthorizationBuilder::new() + .with_label("provide_liquidity") + .with_subroutine( + AtomicSubroutineBuilder::new() + .with_function(cl_lper_function) + .build(), + ) + .build(), + ); + builder.add_authorization( + AuthorizationBuilder::new() + .with_label("withdraw_liquidity") + .with_subroutine( + AtomicSubroutineBuilder::new() + .with_function(cl_lwer_function) + .build(), + ) + .build(), + ); + + let mut program_config = builder.build(); + + // prior to initializing the manager, we do the middleware plumbing + setup_polytone( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_NAME, + NEUTRON_CHAIN_ID, + OSMOSIS_CHAIN_ID, + NEUTRON_CHAIN_DENOM, + OSMOSIS_CHAIN_DENOM, + )?; + + info!("initializing manager..."); + use_manager_init(&mut program_config)?; + + let input_acc_addr = program_config + .get_account(cl_input_acc)? + .addr + .clone() + .unwrap(); + let output_acc_addr = program_config + .get_account(cl_output_acc)? + .addr + .clone() + .unwrap(); + let final_output_acc_addr = program_config + .get_account(final_output_acc)? + .addr + .clone() + .unwrap(); + + info!("input_acc_addr: {input_acc_addr}"); + info!("output_acc_addr: {output_acc_addr}"); + info!("final_output_acc_addr: {final_output_acc_addr}"); + + let input_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + let output_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &output_acc_addr, + ); + let final_output_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &final_output_acc_addr, + ); + info!("input_acc_balances: {:?}", input_acc_balances); + info!("output_acc_balances: {:?}", output_acc_balances); + info!("final_output_acc_balances: {:?}", final_output_acc_balances); + + info!("funding the input account..."); + bank::send( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + DEFAULT_KEY, + &input_acc_addr, + &[ + cosmwasm_std_old::Coin { + denom: ntrn_on_osmo_denom.to_string(), + amount: 1_000_000u128.into(), + }, + cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 1_000_000u128.into(), + }, + ], + &cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 1_000_000u128.into(), + }, + )?; + + std::thread::sleep(Duration::from_secs(3)); + + let input_acc_balances = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + info!("input_acc_balances: {:?}", input_acc_balances); + + // Get authorization and processor contract addresses + let authorization_contract_address = + program_config.authorization_data.authorization_addr.clone(); + let osmo_processor_contract_address = program_config + .get_processor_addr(&osmo_domain.to_string()) + .unwrap(); + let ntrn_processor_contract_address = program_config + .get_processor_addr(&ntrn_domain.to_string()) + .unwrap(); + + info!("authorization contract address: {authorization_contract_address}"); + info!("osmo processor contract address: {osmo_processor_contract_address}"); + info!("ntrn processor contract address: {ntrn_processor_contract_address}"); + + let lp_message = ProcessorMessage::CosmwasmExecuteMsg { + msg: Binary::from(serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_cl_lper::msg::FunctionMsgs::ProvideLiquidityDefault { + bucket_amount: Uint64::new(1), + }, + ), + )?), + }; + let provide_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( + valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { + label: "provide_liquidity".to_string(), + messages: vec![lp_message], + ttl: None, + }, + ); + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + DEFAULT_KEY, + &serde_json::to_string(&provide_liquidity_msg)?, + GAS_FLAGS, + )?; + + info!("confirming that osmosis processor enqueued the provide_liquidity_msg..."); + confirm_remote_domain_processor_queue_length( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + 1, + ); + + info!("Ticking osmo processor..."); + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &osmo_processor_contract_address, + DEFAULT_KEY, + &serde_json::to_string( + &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( + valence_processor_utils::msg::PermissionlessMsg::Tick {}, + ), + )?, + &format!( + "--gas=auto --gas-adjustment=3.0 --fees {}{}", + 5_000_000, OSMOSIS_CHAIN_DENOM + ), + )?; + + std::thread::sleep(std::time::Duration::from_secs(3)); + + info!("asserting that providing liquidity worked..."); + let input_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &input_acc_addr, + ); + + let output_acc_cl_positions = query_cl_position(&mut test_ctx, &output_acc_addr)?; + + info!("input acc bal: {:?}", input_acc_bal); + info!("output acc cl positions: {:?}", output_acc_cl_positions); + + // input acc started with 2 denoms. we provided liquidity with two denoms, + // so we should either be left with 1 or 0 denoms (1 in case of leftover). + assert_ne!(input_acc_bal.len(), 2); + // output acc should now own one CL position + assert_eq!(output_acc_cl_positions.positions.len(), 1); + Ok(()) } diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs index f0d199f1..b8238222 100644 --- a/local-interchaintest/src/utils/osmosis.rs +++ b/local-interchaintest/src/utils/osmosis.rs @@ -60,7 +60,28 @@ pub mod concentrated_liquidity { OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_NAME, }; use log::info; - use serde_json::Value; + use osmosis_std::types::osmosis::concentratedliquidity::v1beta1::UserPositionsResponse; + + pub fn query_cl_position( + test_ctx: &mut TestContext, + addr: &str, + ) -> Result> { + info!("querying {addr} cl positions..."); + + let cmd = format!("concentratedliquidity user-positions {addr} --output=json"); + + let rb = test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME); + + let resp = rb.q(&cmd, false); + + let user_positions: UserPositionsResponse = serde_json::from_value(resp).unwrap(); + + info!("{addr} CL positions: {:?}", user_positions.positions); + + Ok(user_positions) + } pub fn setup_cl_pool( test_ctx: &mut TestContext, @@ -120,6 +141,23 @@ pub mod concentrated_liquidity { let pool_id: u64 = pool_id_str.parse().unwrap(); info!("CL pool id: {:?}", pool_id); + // Usage: + // osmosisd tx concentratedliquidity create-position [pool-id] [lower-tick] [upper-tick] [tokens-provided] [token-min-amount0] [token-min-amount1] [flags] + + // Examples: + // osmosisd tx concentratedliquidity create-position 1 "[-69082]" 69082 10000uosmo,10000uion 0 0 --from val --chain-id osmosis-1 -b block --keyring-backend test --fees 1000uosmo + + let lp_cmd = format!( + "tx concentratedliquidity create-position {pool_id} 1000 2000 10000000uosmo,10000000{denom_2} 0 0 --from={} --fees=5000uosmo --gas auto --gas-adjustment 1.3 --output=json", + DEFAULT_KEY + ); + + let lp_response = test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME) + .tx(&lp_cmd, false)?; + + info!("initial LP response: {:?}", lp_response); Ok(pool_id) } From 7bead44b1c8ae6f6434334f46d9db9dc4c2d23c7 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 21 Nov 2024 18:14:08 +0100 Subject: [PATCH 30/92] wip: debugging cl withdrawal --- local-interchaintest/examples/osmo_cl.rs | 208 +++++++++++++++--- local-interchaintest/src/utils/osmosis.rs | 14 +- .../src/testing/concentrated_liquidity.rs | 14 +- 3 files changed, 193 insertions(+), 43 deletions(-) diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs index 5bc941e0..f19c1317 100644 --- a/local-interchaintest/examples/osmo_cl.rs +++ b/local-interchaintest/examples/osmo_cl.rs @@ -1,7 +1,8 @@ use std::{error::Error, time::Duration}; -use cosmwasm_std::{Binary, Int64, Uint64}; +use cosmwasm_std::{Binary, Int64, Uint128, Uint64}; use local_interchaintest::utils::{ + authorization::confirm_authorizations_callback_state, manager::{ setup_manager, use_manager_init, OSMOSIS_CL_LPER_NAME, OSMOSIS_CL_LWER_NAME, POLYTONE_NOTE_NAME, POLYTONE_PROXY_NAME, POLYTONE_VOICE_NAME, @@ -23,6 +24,7 @@ use valence_authorization_utils::{ authorization_message::{Message, MessageDetails, MessageType}, builders::{AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder}, domain::Domain, + function::{RetryLogic, RetryTimes}, msg::ProcessorMessage, }; use valence_osmosis_utils::utils::cl_utils::TickRange; @@ -52,7 +54,7 @@ fn main() -> Result<(), Box> { .dest(OSMOSIS_CHAIN_NAME) .get(); - let pool_id = setup_cl_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + let pool_id = setup_cl_pool(&mut test_ctx, &ntrn_on_osmo_denom, OSMOSIS_CHAIN_DENOM)?; setup_manager( &mut test_ctx, @@ -90,10 +92,6 @@ fn main() -> Result<(), Box> { let cl_output_acc = builder.add_account(cl_output_acc_info); let final_output_acc = builder.add_account(final_output_acc_info); - info!("cl input acc: {:?}", cl_input_acc); - info!("cl output acc: {:?}", cl_output_acc); - info!("final output acc: {:?}", final_output_acc); - let cl_lper_config = valence_osmosis_cl_lper::msg::LibraryConfig { input_addr: cl_input_acc.clone(), output_addr: cl_output_acc.clone(), @@ -102,8 +100,8 @@ fn main() -> Result<(), Box> { pool_asset_1: ntrn_on_osmo_denom.to_string(), pool_asset_2: OSMOSIS_CHAIN_DENOM.to_string(), global_tick_range: TickRange { - lower_tick: Int64::from(-10_000), - upper_tick: Int64::from(10_000), + lower_tick: Int64::from(-1_000_000), + upper_tick: Int64::from(1_000_000), }, }, }; @@ -175,6 +173,10 @@ fn main() -> Result<(), Box> { .with_subroutine( AtomicSubroutineBuilder::new() .with_function(cl_lwer_function) + // .with_retry_logic(RetryLogic { + // times: RetryTimes::Indefinitely, + // interval: cw_utils::Duration::Time(1), + // }) .build(), ) .build(), @@ -216,27 +218,27 @@ fn main() -> Result<(), Box> { info!("output_acc_addr: {output_acc_addr}"); info!("final_output_acc_addr: {final_output_acc_addr}"); - let input_acc_balances = bank::get_balance( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - &input_acc_addr, - ); - let output_acc_balances = bank::get_balance( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - &output_acc_addr, - ); - let final_output_acc_balances = bank::get_balance( - test_ctx - .get_request_builder() - .get_request_builder(OSMOSIS_CHAIN_NAME), - &final_output_acc_addr, - ); - info!("input_acc_balances: {:?}", input_acc_balances); - info!("output_acc_balances: {:?}", output_acc_balances); - info!("final_output_acc_balances: {:?}", final_output_acc_balances); + // let input_acc_balances = bank::get_balance( + // test_ctx + // .get_request_builder() + // .get_request_builder(OSMOSIS_CHAIN_NAME), + // &input_acc_addr, + // ); + // let output_acc_balances = bank::get_balance( + // test_ctx + // .get_request_builder() + // .get_request_builder(OSMOSIS_CHAIN_NAME), + // &output_acc_addr, + // ); + // let final_output_acc_balances = bank::get_balance( + // test_ctx + // .get_request_builder() + // .get_request_builder(OSMOSIS_CHAIN_NAME), + // &final_output_acc_addr, + // ); + // info!("input_acc_balances: {:?}", input_acc_balances); + // info!("output_acc_balances: {:?}", output_acc_balances); + // info!("final_output_acc_balances: {:?}", final_output_acc_balances); info!("funding the input account..."); bank::send( @@ -257,7 +259,24 @@ fn main() -> Result<(), Box> { ], &cosmwasm_std_old::Coin { denom: OSMOSIS_CHAIN_DENOM.to_string(), - amount: 1_000_000u128.into(), + amount: 5_000u128.into(), + }, + )?; + std::thread::sleep(Duration::from_secs(3)); + + bank::send( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + DEFAULT_KEY, + &output_acc_addr, + &[cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 10_000u128.into(), + }], + &cosmwasm_std_old::Coin { + denom: OSMOSIS_CHAIN_DENOM.to_string(), + amount: 5_000u128.into(), }, )?; @@ -288,8 +307,16 @@ fn main() -> Result<(), Box> { let lp_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from(serde_json::to_vec( &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + // valence_osmosis_cl_lper::msg::FunctionMsgs::ProvideLiquidityCustom { + // tick_range: TickRange { + // lower_tick: Int64::new(1000), + // upper_tick: Int64::new(2000), + // }, + // token_min_amount_0: Some(Uint128::zero()), + // token_min_amount_1: Some(Uint128::zero()), + // }, valence_osmosis_cl_lper::msg::FunctionMsgs::ProvideLiquidityDefault { - bucket_amount: Uint64::new(1), + bucket_amount: Uint64::new(10), }, ), )?), @@ -350,8 +377,11 @@ fn main() -> Result<(), Box> { let output_acc_cl_positions = query_cl_position(&mut test_ctx, &output_acc_addr)?; - info!("input acc bal: {:?}", input_acc_bal); - info!("output acc cl positions: {:?}", output_acc_cl_positions); + info!("[POST-LP] input acc bal: {:?}", input_acc_bal); + info!( + "[POST-LP] output acc cl positions: {:?}", + output_acc_cl_positions + ); // input acc started with 2 denoms. we provided liquidity with two denoms, // so we should either be left with 1 or 0 denoms (1 in case of leftover). @@ -359,5 +389,117 @@ fn main() -> Result<(), Box> { // output acc should now own one CL position assert_eq!(output_acc_cl_positions.positions.len(), 1); + let output_acc_cl_position = output_acc_cl_positions + .positions + .first() + .unwrap() + .position + .clone() + .unwrap(); + + info!("confirmed liquidity provision! asserting authorizations callbacks state sync..."); + confirm_authorizations_callback_state( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + &authorization_contract_address, + 0, + )?; + + let lw_message = ProcessorMessage::CosmwasmExecuteMsg { + msg: Binary::from(serde_json::to_vec( + &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( + valence_osmosis_cl_withdrawer::msg::FunctionMsgs::WithdrawLiquidity { + position_id: output_acc_cl_position.position_id.into(), + liquidity_amount: output_acc_cl_position.liquidity, + }, + ), + )?), + }; + let withdraw_liquidity_msg = valence_authorization_utils::msg::ExecuteMsg::PermissionlessAction( + valence_authorization_utils::msg::PermissionlessMsg::SendMsgs { + label: "withdraw_liquidity".to_string(), + messages: vec![lw_message], + ttl: None, + }, + ); + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &authorization_contract_address, + DEFAULT_KEY, + &serde_json::to_string(&withdraw_liquidity_msg)?, + GAS_FLAGS, + )?; + + std::thread::sleep(std::time::Duration::from_secs(5)); + + info!("confirming that osmosis processor enqueued the withdraw_liquidity_msg..."); + confirm_remote_domain_processor_queue_length( + &mut test_ctx, + OSMOSIS_CHAIN_NAME, + &osmo_processor_contract_address, + 1, + ); + + info!( + "PRE-TICK OUTPUT ACC CL POSITIONS: {:?}", + query_cl_position(&mut test_ctx, &output_acc_addr)?.positions + ); + + info!("Ticking osmo processor to withdraw liquidity..."); + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &osmo_processor_contract_address, + DEFAULT_KEY, + &serde_json::to_string( + &valence_processor_utils::msg::ExecuteMsg::PermissionlessAction( + valence_processor_utils::msg::PermissionlessMsg::Tick {}, + ), + )?, + &format!( + "--gas=auto --gas-adjustment=5.0 --fees {}{}", + 5_000_000, OSMOSIS_CHAIN_DENOM + ), + )?; + + std::thread::sleep(std::time::Duration::from_secs(5)); + + info!("asserting that withdrawing liquidity worked..."); + + let output_acc_cl_positions = query_cl_position(&mut test_ctx, &output_acc_addr)?; + let final_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &final_output_acc_addr, + ); + let output_acc_bal = bank::get_balance( + test_ctx + .get_request_builder() + .get_request_builder(OSMOSIS_CHAIN_NAME), + &output_acc_addr, + ); + info!( + "POST-TICK OUTPUT ACC CL POSITIONS: {:?}", + output_acc_cl_positions.positions + ); + info!("final acc bal: {:?}", final_acc_bal); + info!("output acc bal: {:?}", output_acc_bal); + + // assert_eq!(output_acc_cl_positions.positions.len(), 0); + // assert_eq!(final_acc_bal.len(), 2); + + info!("asserting authorizations callbacks state sync..."); + confirm_authorizations_callback_state( + &mut test_ctx, + NEUTRON_CHAIN_NAME, + &authorization_contract_address, + 1, + )?; + Ok(()) } diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs index b8238222..99778b97 100644 --- a/local-interchaintest/src/utils/osmosis.rs +++ b/local-interchaintest/src/utils/osmosis.rs @@ -111,13 +111,13 @@ pub mod concentrated_liquidity { .get_request_builder(OSMOSIS_CHAIN_NAME); let tick_spacing = 1000; - let spread_factor = 0.0005; + let spread_factor = 0.005; + // denoms here are reversed because second denom is the quote denom which needs to be authorized (uosmo) let cmd = format!( - "tx concentratedliquidity create-pool {denom_2} {denom_1} {tick_spacing} {spread_factor} --fees=5000uosmo --from={} --gas auto --gas-adjustment 1.3 --output=json", + "tx concentratedliquidity create-pool {denom_1} {denom_2} {tick_spacing} {spread_factor} --from={} --fees=5000uosmo --gas auto --gas-adjustment 1.3 --output=json", DEFAULT_KEY ); - info!("CL creation cmd: {cmd}"); let cl_creation_response_events = osmo_rb.tx(&cmd, true)?["events"].clone(); @@ -141,14 +141,10 @@ pub mod concentrated_liquidity { let pool_id: u64 = pool_id_str.parse().unwrap(); info!("CL pool id: {:?}", pool_id); - // Usage: - // osmosisd tx concentratedliquidity create-position [pool-id] [lower-tick] [upper-tick] [tokens-provided] [token-min-amount0] [token-min-amount1] [flags] - - // Examples: - // osmosisd tx concentratedliquidity create-position 1 "[-69082]" 69082 10000uosmo,10000uion 0 0 --from val --chain-id osmosis-1 -b block --keyring-backend test --fees 1000uosmo + // osmosisd tx concentratedliquidity create-position [pool-id] [lower-tick] [upper-tick] [tokens-provided] [token-min-amount0] [token-min-amount1] [flags] let lp_cmd = format!( - "tx concentratedliquidity create-position {pool_id} 1000 2000 10000000uosmo,10000000{denom_2} 0 0 --from={} --fees=5000uosmo --gas auto --gas-adjustment 1.3 --output=json", + "tx concentratedliquidity create-position {pool_id} [-10000] 10000 1500000{denom_1},1500000{denom_2} 0 0 --from={} --fees=5000uosmo --gas auto --gas-adjustment 1.3 --output=json", DEFAULT_KEY ); diff --git a/packages/osmosis-utils/src/testing/concentrated_liquidity.rs b/packages/osmosis-utils/src/testing/concentrated_liquidity.rs index e388d175..f179b7e6 100644 --- a/packages/osmosis-utils/src/testing/concentrated_liquidity.rs +++ b/packages/osmosis-utils/src/testing/concentrated_liquidity.rs @@ -67,7 +67,7 @@ impl OsmosisTestPoolConfig for ConcentratedLiquidityPool { denom0: OSMO_DENOM.to_string(), denom1: TEST_DENOM.to_string(), tick_spacing: 1000, - spread_factor: "500000000000000000".to_string(), + spread_factor: "500000000000000".to_string(), }, creator, ) @@ -98,6 +98,18 @@ impl OsmosisTestPoolConfig for ConcentratedLiquidityPool { pool_asset_2: TEST_DENOM.to_string(), }; + let pool = cl + .query_pools( + &osmosis_std::types::osmosis::concentratedliquidity::v1beta1::PoolsRequest { + pagination: None, + }, + ) + .unwrap(); + + let scl_pool: osmosis_std::types::osmosis::concentratedliquidity::v1beta1::Pool = + pool.pools[0].clone().try_into().unwrap(); + println!("pools: {:?}", scl_pool); + Ok(cl_pool) } } From 19816ff22d4b3270bbfa00fbdced01567588cb77 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 13:41:43 +0100 Subject: [PATCH 31/92] cl withdraw takes in optional dec256 for liquidity amount --- Cargo.lock | 1 + .../osmosis-cl-withdrawer/Cargo.toml | 1 + .../osmosis-cl-withdrawer/src/contract.rs | 87 ++++++++++++++----- .../osmosis-cl-withdrawer/src/msg.rs | 4 +- .../src/testing/test_suite.rs | 10 ++- .../src/testing/tests.rs | 10 ++- local-interchaintest/examples/osmo_cl.rs | 16 ++-- 7 files changed, 91 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b22f0c9..50472a15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5326,6 +5326,7 @@ dependencies = [ name = "valence-osmosis-cl-withdrawer" version = "0.1.0" dependencies = [ + "base64 0.22.1", "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "cw-ownable", diff --git a/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml b/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml index 1018f109..603e4de1 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml +++ b/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml @@ -34,3 +34,4 @@ serde_json = { workspace = true } cw20 = { workspace = true } osmosis-test-tube = { workspace = true } valence-osmosis-utils = { workspace = true, features = ["testing"] } +base64 = "0.22.1" diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs index 6a5229ad..99b0001e 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs @@ -3,14 +3,14 @@ use std::str::FromStr; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, to_json_string, BankMsg, Binary, Coin, Deps, DepsMut, Env, MessageInfo, Reply, - Response, StdError, StdResult, SubMsg, SubMsgResult, Uint128, + ensure, to_json_binary, to_json_string, BankMsg, Binary, CosmosMsg, Decimal256, Deps, DepsMut, + Env, MessageInfo, Reply, Response, StdError, StdResult, SubMsg, SubMsgResult, }; use osmosis_std::types::osmosis::concentratedliquidity::v1beta1::{ - MsgWithdrawPosition, MsgWithdrawPositionResponse, PositionByIdRequest, PositionByIdResponse, + ConcentratedliquidityQuerier, MsgWithdrawPosition, }; -use valence_account_utils::msg::{parse_valence_payload, ValenceCallback}; +use valence_account_utils::msg::parse_valence_payload; use valence_library_utils::{ error::LibraryError, execute_on_behalf_of, execute_submsgs_on_behalf_of, @@ -73,27 +73,49 @@ pub fn try_liquidate_cl_position( deps: DepsMut, cfg: Config, position_id: u64, - liquidity_amount: String, + liquidity_amount: Option, ) -> Result { - // here we just assert that the position exists. - // any validations beyond this (like position ownership, etc.) - // will propagate on execution. - deps.querier - .query::(&PositionByIdRequest { position_id }.into()) - .map_err(|_| StdError::generic_err("no such position"))?; - - let liquidate_position_msg = MsgWithdrawPosition { + // first we query the position + let position_query_response = + ConcentratedliquidityQuerier::new(&deps.querier).position_by_id(position_id)?; + let position = position_query_response + .position + .and_then(|pos| pos.position) + .ok_or_else(|| StdError::generic_err("failed to get cl position"))?; + + // convert the string-based liquidity field to Decimal256 + let total_position_liquidity = Decimal256::from_str(position.liquidity.as_str())?; + + let liquidity_to_withdraw = match liquidity_amount { + // if liquidity amount to be liquidated is specified, + // we ensure that the amount is less than or equal to + // the total liquidity in the position + Some(amt) => { + ensure!( + amt <= total_position_liquidity, + StdError::generic_err(format!( + "Insufficient liquidity: {amt} > {total_position_liquidity}", + )) + ); + amt + } + // if no liquidity amount is specified, we withdraw the entire position + None => total_position_liquidity, + }; + + let liquidate_position_msg: CosmosMsg = MsgWithdrawPosition { position_id, sender: cfg.input_addr.to_string(), - liquidity_amount, - }; + liquidity_amount: liquidity_to_withdraw.atomics().to_string(), + } + .into(); // we delegate the position liquidation msg as a submsg because we // will need to transfer the underlying tokens we liquidate afterwards. let delegated_input_acc_msgs = execute_submsgs_on_behalf_of( vec![SubMsg::reply_on_success(liquidate_position_msg, REPLY_ID)], Some(to_json_string(&cfg)?), - &cfg.input_addr.clone(), + &cfg.input_addr, )?; let lib_submsg = SubMsg::reply_on_success(delegated_input_acc_msgs, REPLY_ID); @@ -139,19 +161,40 @@ fn handle_liquidity_withdrawal_reply( let cfg: Config = parse_valence_payload(&result)?; // decode the response from the submsg result - let valence_callback = ValenceCallback::try_from(result)?; + // let valence_callback = ValenceCallback::try_from(result)?; // decode the underlying position withdrawal response // and query the pool to match the denoms - let decoded_resp: MsgWithdrawPositionResponse = valence_callback.result.try_into()?; + // let decoded_resp: MsgWithdrawPositionResponse = valence_callback.clone().result.try_into()?; let pool = query_cl_pool(&deps, cfg.pool_id.u64())?; + // let mut transfer_coins = vec![]; + + // let amt_1 = Uint128::from_str(&decoded_resp.amount0)?; + // let amt_2 = Uint128::from_str(&decoded_resp.amount1)?; + + // if !amt_1.is_zero() { + // transfer_coins.push(Coin::new(amt_1, pool.token0.to_string())); + // } + // if !amt_2.is_zero() { + // transfer_coins.push(Coin::new(amt_2, pool.token1.to_string())); + // } + // let transfer_msg = BankMsg::Send { + // to_address: cfg.output_addr.to_string(), + // amount: transfer_coins, + // }; + + let post_withdraw_balance_t0 = deps + .querier + .query_balance(cfg.input_addr.to_string(), &pool.token0)?; + + let post_withdraw_balance_t1 = deps + .querier + .query_balance(cfg.input_addr.to_string(), &pool.token1)?; + let transfer_msg = BankMsg::Send { to_address: cfg.output_addr.to_string(), - amount: vec![ - Coin::new(Uint128::from_str(&decoded_resp.amount0)?, pool.token0), - Coin::new(Uint128::from_str(&decoded_resp.amount1)?, pool.token1), - ], + amount: vec![post_withdraw_balance_t0, post_withdraw_balance_t1], }; Ok(Response::default().add_message(execute_on_behalf_of( diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/msg.rs b/contracts/libraries/osmosis-cl-withdrawer/src/msg.rs index 9b8aabb9..99c75f40 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/msg.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/msg.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Deps, DepsMut, Uint64}; +use cosmwasm_std::{Addr, Decimal256, Deps, DepsMut, Uint64}; use cw_ownable::cw_ownable_query; use valence_library_utils::{ @@ -16,7 +16,7 @@ pub enum FunctionMsgs { // ID of the position to be liquidated position_id: Uint64, // in sdk this is a `Dec`, which prost translates to a `String` - liquidity_amount: String, + liquidity_amount: Option, }, } diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/testing/test_suite.rs b/contracts/libraries/osmosis-cl-withdrawer/src/testing/test_suite.rs index d988f3a8..12473898 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/testing/test_suite.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/testing/test_suite.rs @@ -1,4 +1,6 @@ -use cosmwasm_std::{coin, Coin, Int64}; +use std::str::FromStr; + +use cosmwasm_std::{coin, Coin, Decimal256, Int64}; use osmosis_std::{ cosmwasm_to_proto_coins, @@ -125,15 +127,17 @@ impl LPerTestSuite { pub fn liquidate_position( &self, position_id: u64, - liquidity_amount: String, + liquidity_amount: Option, ) -> ExecuteResponse { let wasm = Wasm::new(&self.inner.app); + let liquidity_to_withdraw = liquidity_amount.map(|amt| Decimal256::from_str(&amt).unwrap()); + wasm.execute::>( &self.lw_addr, &ExecuteMsg::ProcessFunction(FunctionMsgs::WithdrawLiquidity { position_id: position_id.into(), - liquidity_amount, + liquidity_amount: liquidity_to_withdraw, }), &[], self.inner.processor_acc(), diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs index 18381ae6..571ad07d 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs @@ -1,4 +1,6 @@ -use cosmwasm_std::coin; +use std::str::FromStr; + +use cosmwasm_std::{coin, Decimal256}; use valence_osmosis_utils::suite::{OSMO_DENOM, TEST_DENOM}; use super::test_suite::LPerTestSuite; @@ -31,7 +33,7 @@ fn test_liquidate_position_basic() { assert_eq!(pre_liq_input_acc_position.position_id, 2); // liquidate the position - suite.liquidate_position(2, pre_liq_input_acc_position.liquidity); + suite.liquidate_position(2, Some(pre_liq_input_acc_position.liquidity)); let post_liq_input_acc_bals = suite .inner @@ -58,7 +60,7 @@ fn test_liquidate_not_owned_position() { coin(1_000_000u128, OSMO_DENOM), coin(1_000_000u128, TEST_DENOM), ]) - .liquidate_position(1, "123".to_string()); + .liquidate_position(1, Some("123".to_string())); } #[test] @@ -69,5 +71,5 @@ fn test_liquidate_non_existing_position() { coin(1_000_000u128, OSMO_DENOM), coin(1_000_000u128, TEST_DENOM), ]) - .liquidate_position(3, "123".to_string()); + .liquidate_position(3, Some("123".to_string())); } diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs index f19c1317..406a5c88 100644 --- a/local-interchaintest/examples/osmo_cl.rs +++ b/local-interchaintest/examples/osmo_cl.rs @@ -1,6 +1,6 @@ -use std::{error::Error, time::Duration}; +use std::{error::Error, str::FromStr, time::Duration}; -use cosmwasm_std::{Binary, Int64, Uint128, Uint64}; +use cosmwasm_std::{Binary, Decimal256, Int64, Uint64}; use local_interchaintest::utils::{ authorization::confirm_authorizations_callback_state, manager::{ @@ -173,10 +173,10 @@ fn main() -> Result<(), Box> { .with_subroutine( AtomicSubroutineBuilder::new() .with_function(cl_lwer_function) - // .with_retry_logic(RetryLogic { - // times: RetryTimes::Indefinitely, - // interval: cw_utils::Duration::Time(1), - // }) + .with_retry_logic(RetryLogic { + times: RetryTimes::Amount(3), + interval: cw_utils::Duration::Time(1), + }) .build(), ) .build(), @@ -405,12 +405,14 @@ fn main() -> Result<(), Box> { 0, )?; + let liquidity_amount = Decimal256::from_str(&output_acc_cl_position.liquidity)?; + let lw_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from(serde_json::to_vec( &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( valence_osmosis_cl_withdrawer::msg::FunctionMsgs::WithdrawLiquidity { position_id: output_acc_cl_position.position_id.into(), - liquidity_amount: output_acc_cl_position.liquidity, + liquidity_amount: Some(liquidity_amount), }, ), )?), From bc5f28cc162c3273b8dfaee336a70a35f5909d58 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 14:05:19 +0100 Subject: [PATCH 32/92] cleanup reply handler; add comments --- .../osmosis-cl-withdrawer/src/contract.rs | 53 ++++++++----------- .../src/testing/tests.rs | 3 +- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs index 99b0001e..00de1023 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs @@ -3,14 +3,14 @@ use std::str::FromStr; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure, to_json_binary, to_json_string, BankMsg, Binary, CosmosMsg, Decimal256, Deps, DepsMut, - Env, MessageInfo, Reply, Response, StdError, StdResult, SubMsg, SubMsgResult, + ensure, to_json_binary, to_json_string, BankMsg, Binary, Coin, CosmosMsg, Decimal256, Deps, + DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, SubMsg, SubMsgResult, Uint128, }; use osmosis_std::types::osmosis::concentratedliquidity::v1beta1::{ - ConcentratedliquidityQuerier, MsgWithdrawPosition, + ConcentratedliquidityQuerier, MsgWithdrawPosition, MsgWithdrawPositionResponse, }; -use valence_account_utils::msg::parse_valence_payload; +use valence_account_utils::msg::{parse_valence_payload, ValenceCallback}; use valence_library_utils::{ error::LibraryError, execute_on_behalf_of, execute_submsgs_on_behalf_of, @@ -84,7 +84,7 @@ pub fn try_liquidate_cl_position( .ok_or_else(|| StdError::generic_err("failed to get cl position"))?; // convert the string-based liquidity field to Decimal256 - let total_position_liquidity = Decimal256::from_str(position.liquidity.as_str())?; + let total_position_liquidity = Decimal256::from_str(&position.liquidity)?; let liquidity_to_withdraw = match liquidity_amount { // if liquidity amount to be liquidated is specified, @@ -161,40 +161,33 @@ fn handle_liquidity_withdrawal_reply( let cfg: Config = parse_valence_payload(&result)?; // decode the response from the submsg result - // let valence_callback = ValenceCallback::try_from(result)?; + let valence_callback = ValenceCallback::try_from(result)?; // decode the underlying position withdrawal response - // and query the pool to match the denoms - // let decoded_resp: MsgWithdrawPositionResponse = valence_callback.clone().result.try_into()?; + // and query the pool to ensure denom ordering + let decoded_resp: MsgWithdrawPositionResponse = valence_callback.result.try_into()?; let pool = query_cl_pool(&deps, cfg.pool_id.u64())?; - // let mut transfer_coins = vec![]; + let mut transfer_coins = vec![]; - // let amt_1 = Uint128::from_str(&decoded_resp.amount0)?; - // let amt_2 = Uint128::from_str(&decoded_resp.amount1)?; + let amt_0 = Uint128::from_str(&decoded_resp.amount0)?; + let amt_1 = Uint128::from_str(&decoded_resp.amount1)?; - // if !amt_1.is_zero() { - // transfer_coins.push(Coin::new(amt_1, pool.token0.to_string())); - // } - // if !amt_2.is_zero() { - // transfer_coins.push(Coin::new(amt_2, pool.token1.to_string())); - // } - // let transfer_msg = BankMsg::Send { - // to_address: cfg.output_addr.to_string(), - // amount: transfer_coins, - // }; - - let post_withdraw_balance_t0 = deps - .querier - .query_balance(cfg.input_addr.to_string(), &pool.token0)?; - - let post_withdraw_balance_t1 = deps - .querier - .query_balance(cfg.input_addr.to_string(), &pool.token1)?; + // there may be situations where only one coin was withdrawn. + // to avoid sending empty coins, we only include non-0-bal coins + if !amt_0.is_zero() { + transfer_coins.push(Coin::new(amt_0, pool.token0)); + } + if !amt_1.is_zero() { + transfer_coins.push(Coin::new(amt_1, pool.token1)); + } + // both coins cannot be zero because that would mean the position + // had no underlying liquidity to withdraw, so we skip the empty + // array check here and just fire the banksend let transfer_msg = BankMsg::Send { to_address: cfg.output_addr.to_string(), - amount: vec![post_withdraw_balance_t0, post_withdraw_balance_t1], + amount: transfer_coins, }; Ok(Response::default().add_message(execute_on_behalf_of( diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs index 571ad07d..6dcf56b5 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs @@ -1,6 +1,5 @@ -use std::str::FromStr; -use cosmwasm_std::{coin, Decimal256}; +use cosmwasm_std::{coin}; use valence_osmosis_utils::suite::{OSMO_DENOM, TEST_DENOM}; use super::test_suite::LPerTestSuite; From 1bbdcaea410c7f242528e89ad26675f9bb4fd28d Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 14:32:58 +0100 Subject: [PATCH 33/92] extend unit tests --- .../osmosis-cl-withdrawer/src/contract.rs | 2 +- .../src/testing/tests.rs | 99 ++++++++++++++++++- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs index 00de1023..9dff57df 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/contract.rs @@ -94,7 +94,7 @@ pub fn try_liquidate_cl_position( ensure!( amt <= total_position_liquidity, StdError::generic_err(format!( - "Insufficient liquidity: {amt} > {total_position_liquidity}", + "insufficient liquidity: {amt} > {total_position_liquidity}", )) ); amt diff --git a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs index 6dcf56b5..87ced5a6 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs +++ b/contracts/libraries/osmosis-cl-withdrawer/src/testing/tests.rs @@ -1,11 +1,12 @@ +use std::str::FromStr; -use cosmwasm_std::{coin}; +use cosmwasm_std::{coin, Decimal256}; use valence_osmosis_utils::suite::{OSMO_DENOM, TEST_DENOM}; use super::test_suite::LPerTestSuite; #[test] -fn test_liquidate_position_basic() { +fn test_liquidate_position_with_amount_specified() { let suite = LPerTestSuite::new(vec![ coin(1_000_000u128, OSMO_DENOM), coin(1_000_000u128, TEST_DENOM), @@ -31,8 +32,69 @@ fn test_liquidate_position_basic() { assert_eq!(pre_liq_input_acc_position.pool_id, 1); assert_eq!(pre_liq_input_acc_position.position_id, 2); - // liquidate the position - suite.liquidate_position(2, Some(pre_liq_input_acc_position.liquidity)); + let available_liquidity = Decimal256::from_str(&pre_liq_input_acc_position.liquidity).unwrap(); + + // calculate 1/2 of the available position liquidity + let half_of_liquidity = available_liquidity / Decimal256::from_str("2.0").unwrap().atomics(); + + // liquidate the half of the position + suite.liquidate_position(2, Some(half_of_liquidity.to_string())); + + let post_liq_input_acc_bals = suite + .inner + .query_all_balances(suite.input_acc.as_str()) + .unwrap(); + let post_liq_output_acc_bals = suite + .inner + .query_all_balances(suite.output_acc.as_str()) + .unwrap(); + let post_liq_input_acc_positions = suite.query_cl_positions(suite.input_acc.to_string()); + + // assert that the position still exists and that the output account received 1/2 + // of the underlying funds + assert_eq!(post_liq_input_acc_bals, vec![]); + assert_eq!(post_liq_output_acc_bals.len(), 2); + assert_eq!(post_liq_input_acc_positions.positions.len(), 1); + + // liquidate the remaining position + suite.liquidate_position(2, Some(half_of_liquidity.to_string())); + + let final_liq_input_acc_positions = suite.query_cl_positions(suite.input_acc.to_string()); + + // assert that the position no longer exists + assert!(final_liq_input_acc_positions.positions.is_empty()); +} + +#[test] +fn test_liquidate_position_default_amount() { + let suite = LPerTestSuite::new(vec![ + coin(1_000_000u128, OSMO_DENOM), + coin(1_000_000u128, TEST_DENOM), + ]); + + let pre_liq_input_acc_bals = suite + .inner + .query_all_balances(suite.input_acc.as_str()) + .unwrap(); + let pre_liq_output_acc_bals = suite + .inner + .query_all_balances(suite.output_acc.as_str()) + .unwrap(); + let pre_liq_input_acc_position = suite + .query_cl_positions(suite.input_acc.to_string()) + .positions[0] + .position + .clone() + .unwrap(); + + assert_eq!(pre_liq_input_acc_bals, vec![]); + assert_eq!(pre_liq_output_acc_bals, vec![]); + assert_eq!(pre_liq_input_acc_position.pool_id, 1); + assert_eq!(pre_liq_input_acc_position.position_id, 2); + + // liquidate the entire position by not specifying the amount + // which defaults to the entire position + suite.liquidate_position(2, None); let post_liq_input_acc_bals = suite .inner @@ -63,7 +125,7 @@ fn test_liquidate_not_owned_position() { } #[test] -#[should_panic(expected = "no such position")] +#[should_panic] fn test_liquidate_non_existing_position() { // position 3 does not exist yet LPerTestSuite::new(vec![ @@ -72,3 +134,30 @@ fn test_liquidate_non_existing_position() { ]) .liquidate_position(3, Some("123".to_string())); } + +#[test] +#[should_panic(expected = "insufficient liquidity:")] +fn test_liquidate_insufficient_liquidity_amount() { + let suite = LPerTestSuite::new(vec![ + coin(1_000_000u128, OSMO_DENOM), + coin(1_000_000u128, TEST_DENOM), + ]); + + let pre_liq_input_acc_position = suite + .query_cl_positions(suite.input_acc.to_string()) + .positions[0] + .position + .clone() + .unwrap(); + + let available_liquidity = Decimal256::from_str(&pre_liq_input_acc_position.liquidity).unwrap(); + + // calculate 2x of the available position liquidity + let double_liquidity = available_liquidity + .checked_add(available_liquidity) + .unwrap() + .atomics(); + + // attempt to liquidate 2x the available liquidity + suite.liquidate_position(2, Some(double_liquidity.to_string())); +} From 2a03ef910661ed72ba8c31d30ad1233d19849c59 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 14:37:01 +0100 Subject: [PATCH 34/92] schema regen --- .../schema/valence-osmosis-cl-withdrawer.json | 14 +- .../schema/valence-program-manager.json | 140 ++++++++++++++++++ 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/contracts/libraries/osmosis-cl-withdrawer/schema/valence-osmosis-cl-withdrawer.json b/contracts/libraries/osmosis-cl-withdrawer/schema/valence-osmosis-cl-withdrawer.json index 451ef336..351601d9 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/schema/valence-osmosis-cl-withdrawer.json +++ b/contracts/libraries/osmosis-cl-withdrawer/schema/valence-osmosis-cl-withdrawer.json @@ -219,6 +219,10 @@ } ] }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, "Expiration": { "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", "oneOf": [ @@ -278,12 +282,18 @@ "withdraw_liquidity": { "type": "object", "required": [ - "liquidity_amount", "position_id" ], "properties": { "liquidity_amount": { - "type": "string" + "anyOf": [ + { + "$ref": "#/definitions/Decimal256" + }, + { + "type": "null" + } + ] }, "position_id": { "$ref": "#/definitions/Uint64" diff --git a/program-manager/schema/valence-program-manager.json b/program-manager/schema/valence-program-manager.json index b6f9faf7..0089506a 100644 --- a/program-manager/schema/valence-program-manager.json +++ b/program-manager/schema/valence-program-manager.json @@ -567,6 +567,10 @@ }, "additionalProperties": false }, + "Int64": { + "description": "An implementation of i64 that is using strings for JSON encoding/decoding, such that the full i64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `i64` to get the value out:\n\n``` # use cosmwasm_std::Int64; let a = Int64::from(258i64); assert_eq!(a.i64(), 258); ```", + "type": "string" + }, "LibraryAccountType": { "description": "An account type that is used in the library configs It can either be an Id or Addr The config that will be passed to the library must be of Addr veriant", "oneOf": [ @@ -703,9 +707,69 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ValenceOsmosisClLper" + ], + "properties": { + "ValenceOsmosisClLper": { + "$ref": "#/definitions/LibraryConfigUpdate9" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ValenceOsmosisClWithdrawer" + ], + "properties": { + "ValenceOsmosisClWithdrawer": { + "$ref": "#/definitions/LibraryConfigUpdate10" + } + }, + "additionalProperties": false } ] }, + "LibraryConfigUpdate10": { + "type": "object", + "properties": { + "input_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + }, + "output_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + }, + "pool_id": { + "anyOf": [ + { + "$ref": "#/definitions/Uint64" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, "LibraryConfigUpdate2": { "type": "object", "properties": { @@ -967,6 +1031,42 @@ }, "additionalProperties": false }, + "LibraryConfigUpdate9": { + "type": "object", + "properties": { + "input_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + }, + "lp_config": { + "anyOf": [ + { + "$ref": "#/definitions/LiquidityProviderConfig3" + }, + { + "type": "null" + } + ] + }, + "output_addr": { + "anyOf": [ + { + "$ref": "#/definitions/LibraryAccountType" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, "LibraryInfo": { "type": "object", "required": [ @@ -1083,6 +1183,30 @@ }, "additionalProperties": false }, + "LiquidityProviderConfig3": { + "type": "object", + "required": [ + "global_tick_range", + "pool_asset_1", + "pool_asset_2", + "pool_id" + ], + "properties": { + "global_tick_range": { + "$ref": "#/definitions/TickRange" + }, + "pool_asset_1": { + "type": "string" + }, + "pool_asset_2": { + "type": "string" + }, + "pool_id": { + "$ref": "#/definitions/Uint64" + } + }, + "additionalProperties": false + }, "LiquidityWithdrawerConfig": { "type": "object", "required": [ @@ -1611,6 +1735,22 @@ } ] }, + "TickRange": { + "type": "object", + "required": [ + "lower_tick", + "upper_tick" + ], + "properties": { + "lower_tick": { + "$ref": "#/definitions/Int64" + }, + "upper_tick": { + "$ref": "#/definitions/Int64" + } + }, + "additionalProperties": false + }, "Timestamp": { "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", "allOf": [ From 7827c3441ede8b38f1e2d18bf41ccd02705dc564 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 14:44:04 +0100 Subject: [PATCH 35/92] cleanup e2e --- local-interchaintest/examples/osmo_cl.rs | 38 ++---------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/local-interchaintest/examples/osmo_cl.rs b/local-interchaintest/examples/osmo_cl.rs index 406a5c88..03668c24 100644 --- a/local-interchaintest/examples/osmo_cl.rs +++ b/local-interchaintest/examples/osmo_cl.rs @@ -173,10 +173,6 @@ fn main() -> Result<(), Box> { .with_subroutine( AtomicSubroutineBuilder::new() .with_function(cl_lwer_function) - .with_retry_logic(RetryLogic { - times: RetryTimes::Amount(3), - interval: cw_utils::Duration::Time(1), - }) .build(), ) .build(), @@ -218,28 +214,6 @@ fn main() -> Result<(), Box> { info!("output_acc_addr: {output_acc_addr}"); info!("final_output_acc_addr: {final_output_acc_addr}"); - // let input_acc_balances = bank::get_balance( - // test_ctx - // .get_request_builder() - // .get_request_builder(OSMOSIS_CHAIN_NAME), - // &input_acc_addr, - // ); - // let output_acc_balances = bank::get_balance( - // test_ctx - // .get_request_builder() - // .get_request_builder(OSMOSIS_CHAIN_NAME), - // &output_acc_addr, - // ); - // let final_output_acc_balances = bank::get_balance( - // test_ctx - // .get_request_builder() - // .get_request_builder(OSMOSIS_CHAIN_NAME), - // &final_output_acc_addr, - // ); - // info!("input_acc_balances: {:?}", input_acc_balances); - // info!("output_acc_balances: {:?}", output_acc_balances); - // info!("final_output_acc_balances: {:?}", final_output_acc_balances); - info!("funding the input account..."); bank::send( test_ctx @@ -307,14 +281,6 @@ fn main() -> Result<(), Box> { let lp_message = ProcessorMessage::CosmwasmExecuteMsg { msg: Binary::from(serde_json::to_vec( &valence_library_utils::msg::ExecuteMsg::<_, ()>::ProcessFunction( - // valence_osmosis_cl_lper::msg::FunctionMsgs::ProvideLiquidityCustom { - // tick_range: TickRange { - // lower_tick: Int64::new(1000), - // upper_tick: Int64::new(2000), - // }, - // token_min_amount_0: Some(Uint128::zero()), - // token_min_amount_1: Some(Uint128::zero()), - // }, valence_osmosis_cl_lper::msg::FunctionMsgs::ProvideLiquidityDefault { bucket_amount: Uint64::new(10), }, @@ -492,8 +458,8 @@ fn main() -> Result<(), Box> { info!("final acc bal: {:?}", final_acc_bal); info!("output acc bal: {:?}", output_acc_bal); - // assert_eq!(output_acc_cl_positions.positions.len(), 0); - // assert_eq!(final_acc_bal.len(), 2); + assert_eq!(output_acc_cl_positions.positions.len(), 0); + assert_eq!(final_acc_bal.len(), 2); info!("asserting authorizations callbacks state sync..."); confirm_authorizations_callback_state( From 24fc336d8f5a01facc6e664d40f6811f1c7b029d Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 15:20:08 +0100 Subject: [PATCH 36/92] include osmo cl e2e run in ci --- .github/workflows/check-ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/check-ci.yml b/.github/workflows/check-ci.yml index 056fd310..ba163e1e 100644 --- a/.github/workflows/check-ci.yml +++ b/.github/workflows/check-ci.yml @@ -242,3 +242,17 @@ jobs: with: chain-config: 'neutron_osmosis' test-name: 'osmo_gamm' + + local-ic-osmo-cl-tests: + needs: [build,setup-local-ic] + name: Osmosis concentrated liquidity e2e lp -> lw run + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run osmo cl lp & lw tests + uses: "./.github/actions/run-local-ic-test" + with: + chain-config: 'neutron_osmosis' + test-name: 'osmo_cl' From 6ea62450284f6281f7bb4d880c76b927ed82d708 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 22 Nov 2024 15:29:20 +0100 Subject: [PATCH 37/92] remove unused dep; update readme --- Cargo.lock | 1 - contracts/libraries/osmosis-cl-withdrawer/Cargo.toml | 1 - contracts/libraries/osmosis-cl-withdrawer/README.md | 6 +++++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2227dc29..7b14d388 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5313,7 +5313,6 @@ dependencies = [ name = "valence-osmosis-cl-withdrawer" version = "0.1.0" dependencies = [ - "base64 0.22.1", "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "cw-ownable", diff --git a/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml b/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml index 603e4de1..1018f109 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml +++ b/contracts/libraries/osmosis-cl-withdrawer/Cargo.toml @@ -34,4 +34,3 @@ serde_json = { workspace = true } cw20 = { workspace = true } osmosis-test-tube = { workspace = true } valence-osmosis-utils = { workspace = true, features = ["testing"] } -base64 = "0.22.1" diff --git a/contracts/libraries/osmosis-cl-withdrawer/README.md b/contracts/libraries/osmosis-cl-withdrawer/README.md index 0ce28980..9b43aed2 100644 --- a/contracts/libraries/osmosis-cl-withdrawer/README.md +++ b/contracts/libraries/osmosis-cl-withdrawer/README.md @@ -6,7 +6,8 @@ positions on Osmosis. A single function is exposed - `withdraw_liquidity`. It takes in two parameters: - `position_id`, specifying the ID of the position to be liquidated -- `liquidity_amount`, specifying the amount of liquidity to be withdrawn +- `liquidity_amount`, specifying an optional amount of liquidity to be withdrawn +expressed in `Decimal256` format ## Validations @@ -14,6 +15,9 @@ During the library validation, both input and output addresses are validated. In addition, a sanity check is performed on the specified pool id to ensure that the pool indeed exists. +If `liquidity_amount` is specified, it gets validated to be less than or equal +to the total liquidity of the position. + ## Function On function execution, the only explicit validation performed is that of ensuring From 303df347bab9bbc24fdc78f7561464060b61ff4a Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 25 Nov 2024 11:36:39 +0100 Subject: [PATCH 38/92] init test icq library --- Cargo.toml | 1 + contracts/testing/test-icq-lib/Cargo.toml | 24 +++ .../testing/test-icq-lib/src/contract.rs | 130 ++++++++++++++ contracts/testing/test-icq-lib/src/icq.rs | 169 ++++++++++++++++++ contracts/testing/test-icq-lib/src/lib.rs | 4 + contracts/testing/test-icq-lib/src/msg.rs | 24 +++ contracts/testing/test-icq-lib/src/state.rs | 25 +++ 7 files changed, 377 insertions(+) create mode 100644 contracts/testing/test-icq-lib/Cargo.toml create mode 100644 contracts/testing/test-icq-lib/src/contract.rs create mode 100644 contracts/testing/test-icq-lib/src/icq.rs create mode 100644 contracts/testing/test-icq-lib/src/lib.rs create mode 100644 contracts/testing/test-icq-lib/src/msg.rs create mode 100644 contracts/testing/test-icq-lib/src/state.rs diff --git a/Cargo.toml b/Cargo.toml index 7bba543a..337e723e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ valence-processor = { path = "contracts/processor", features valence-splitter-library = { path = "contracts/libraries/splitter", features = ["library"] } valence-test-dynamic-ratio = { path = "contracts/testing/test-dynamic-ratio", features = ["library"] } valence-test-library = { path = "contracts/testing/test-library", features = ["library"] } +valence-test-icq-lib = { path = "contracts/testing/test-icq-lib", features = ["library"] } valence-workflow-registry = { path = "contracts/workflow-registry", features = ["library"] } valence-astroport-lper = { path = "contracts/libraries/astroport-lper", features = ["library"] } valence-forwarder-library = { path = "contracts/libraries/forwarder", features = ["library"] } diff --git a/contracts/testing/test-icq-lib/Cargo.toml b/contracts/testing/test-icq-lib/Cargo.toml new file mode 100644 index 00000000..d8fd2158 --- /dev/null +++ b/contracts/testing/test-icq-lib/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "valence-test-icq-lib" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } +valence-processor-utils = { workspace = true } +neutron-sdk = { workspace = true } +serde-json-wasm = "1.0.0" +cw2 = { workspace = true } +cosmos-sdk-proto = { workspace = true } diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs new file mode 100644 index 00000000..eccf3ad3 --- /dev/null +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -0,0 +1,130 @@ +use crate::icq; +use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; +use crate::state::OpenAckVersion; +use crate::state::{RECIPIENT_TXS, TRANSFERS}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{ + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, +}; +use cw2::set_contract_version; +use neutron_sdk::{ + bindings::{msg::NeutronMsg, query::NeutronQuery}, + interchain_queries::v047::queries::{query_balance, BalanceResponse}, + sudo::msg::SudoMsg, + NeutronResult, +}; + +pub const CONTRACT_NAME: &str = "orbital-core"; +pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub type QueryDeps<'a> = Deps<'a, NeutronQuery>; +pub type ExecuteDeps<'a> = DepsMut<'a, NeutronQuery>; + +#[entry_point] +pub fn instantiate( + deps: ExecuteDeps, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> NeutronResult> { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + Ok(Response::new()) +} + +#[entry_point] +pub fn execute( + deps: ExecuteDeps, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> NeutronResult> { + match msg { + ExecuteMsg::RegisterBalancesQuery { + connection_id, + update_period, + addr, + denoms, + } => icq::register_balances_query(connection_id, addr, denoms, update_period), + } +} + +#[entry_point] +pub fn query(deps: QueryDeps, env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Balance { query_id } => to_json_binary(&query_icq_balance(deps, env, query_id)?), + } +} + +fn query_icq_balance(deps: QueryDeps, env: Env, query_id: u64) -> StdResult { + query_balance(deps, env, query_id).map_err(|e| StdError::generic_err(e.to_string())) +} + +#[entry_point] +pub fn reply(_deps: ExecuteDeps, _env: Env, _msg: Reply) -> StdResult> { + unimplemented!() +} + +#[entry_point] +pub fn migrate(_deps: ExecuteDeps, _env: Env, _msg: MigrateMsg) -> StdResult> { + unimplemented!() +} + +// neutron uses the `sudo` entry point in their ICA/ICQ related logic +#[entry_point] +pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult> { + match msg { + // For handling successful registering of ICA + SudoMsg::OpenAck { + port_id, + channel_id, + counterparty_channel_id, + counterparty_version, + } => sudo_open_ack( + deps, + env, + port_id, + channel_id, + counterparty_channel_id, + counterparty_version, + ), + // For handling tx query result + SudoMsg::TxQueryResult { + query_id, + height, + data, + } => icq::sudo_tx_query_result(deps, env, query_id, height, data), + + // For handling kv query result + SudoMsg::KVQueryResult { query_id } => icq::sudo_kv_query_result(deps, env, query_id), + _ => Ok(Response::default()), + } +} + +// handler +fn sudo_open_ack( + deps: ExecuteDeps, + _env: Env, + port_id: String, + _channel_id: String, + _counterparty_channel_id: String, + counterparty_version: String, +) -> StdResult> { + // parse the response + let parsed_version: OpenAckVersion = + serde_json_wasm::from_str(counterparty_version.as_str()) + .map_err(|_| StdError::generic_err("Can't parse counterparty_version"))?; + + // // extract the ICA identifier from the port + // let ica_identifier = extract_ica_identifier_from_port(port_id)?; + + // let clearing_account_config = ClearingAccountConfig { + // addr: parsed_version.address, + // controller_connection_id: parsed_version.controller_connection_id, + // }; + + // // Update the storage record associated with the interchain account. + // CLEARING_ACCOUNTS.save(deps.storage, ica_identifier, &Some(clearing_account_config))?; + + Ok(Response::default()) +} diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs new file mode 100644 index 00000000..f9404922 --- /dev/null +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -0,0 +1,169 @@ +use cosmos_sdk_proto::{ + cosmos::{ + bank::v1beta1::MsgSend, + tx::v1beta1::{TxBody, TxRaw}, + }, + prost::Message, +}; +use cosmwasm_std::{Binary, DepsMut, Env, Response}; +use neutron_sdk::{ + bindings::{msg::NeutronMsg, query::NeutronQuery, types::Height}, + interchain_queries::{ + get_registered_query, + v045::{new_register_balances_query_msg, new_register_transfers_query_msg}, + }, + NeutronResult, +}; + +use cosmwasm_std::{StdError, StdResult}; + +use neutron_sdk::bindings::query::QueryRegisteredQueryResponse; +use neutron_sdk::interchain_queries::v047::types::{COSMOS_SDK_TRANSFER_MSG_URL, RECIPIENT_FIELD}; + +use neutron_sdk::interchain_queries::types::{ + TransactionFilterItem, TransactionFilterOp, TransactionFilterValue, +}; +use serde_json_wasm; + +use crate::state::{Transfer, RECIPIENT_TXS, TRANSFERS}; + +const MAX_ALLOWED_MESSAGES: usize = 20; + +pub fn register_balances_query( + connection_id: String, + addr: String, + denoms: Vec, + update_period: u64, +) -> NeutronResult> { + let msg = new_register_balances_query_msg(connection_id, addr, denoms, update_period)?; + + Ok(Response::new().add_message(msg)) +} + +/// sudo_check_tx_query_result is an example callback for transaction query results that stores the +/// deposits received as a result on the registered query in the contract's state. +pub fn sudo_tx_query_result( + deps: DepsMut, + _env: Env, + query_id: u64, + _height: Height, + data: Binary, +) -> StdResult> { + // Decode the transaction data + let tx: TxRaw = TxRaw::decode(data.as_slice()) + .map_err(|_| StdError::generic_err("sudo_tx_query_result failed to decode tx_raw"))?; + let body: TxBody = TxBody::decode(tx.body_bytes.as_slice()) + .map_err(|_| StdError::generic_err("sudo_tx_query_result failed to decode tx_body"))?; + + // Get the registered query by ID and retrieve the raw query string + let registered_query: QueryRegisteredQueryResponse = + get_registered_query(deps.as_ref(), query_id).map_err(|_| { + StdError::generic_err("sudo_tx_query_result failed to get registered query response") + })?; + let transactions_filter = registered_query.registered_query.transactions_filter; + + #[allow(clippy::match_single_binding)] + match registered_query.registered_query.query_type { + _ => { + // For transfer queries, query data looks like `[{"field:"transfer.recipient", "op":"eq", "value":"some_address"}]` + let query_data: Vec = + serde_json_wasm::from_str(transactions_filter.as_str()).map_err(|_| { + StdError::generic_err("sudo_tx_query_result failed to parse tx query type") + })?; + + let recipient = query_data + .iter() + .find(|x| x.field == RECIPIENT_FIELD && x.op == TransactionFilterOp::Eq) + .map(|x| match &x.value { + TransactionFilterValue::String(v) => v.as_str(), + _ => "", + }) + .unwrap_or(""); + + let deposits = recipient_deposits_from_tx_body(body, recipient).map_err(|_| { + StdError::generic_err( + "sudo_tx_query_result failed to decode recipient deposits from tx body", + ) + })?; + // If we didn't find a Send message with the correct recipient, return an error, and + // this query result will be rejected by Neutron: no data will be saved to state. + if deposits.is_empty() { + return Err(StdError::generic_err( + "failed to find a matching transaction message", + )); + } + + let mut stored_transfers: u64 = TRANSFERS.load(deps.storage).unwrap_or_default(); + stored_transfers += deposits.len() as u64; + TRANSFERS.save(deps.storage, &stored_transfers)?; + + let mut stored_deposits: Vec = RECIPIENT_TXS + .load(deps.storage, recipient.to_string()) + .unwrap_or_default(); + stored_deposits.extend(deposits); + RECIPIENT_TXS.save(deps.storage, recipient.to_string(), &stored_deposits)?; + Ok(Response::new()) + } + } +} + +/// parses tx body and retrieves transactions to the given recipient. +fn recipient_deposits_from_tx_body( + tx_body: TxBody, + recipient: &str, +) -> NeutronResult> { + let mut deposits: Vec = vec![]; + // Only handle up to MAX_ALLOWED_MESSAGES messages, everything else + // will be ignored to prevent 'out of gas' conditions. + // Note: in real contracts you will have to somehow save ignored + // data in order to handle it later. + for msg in tx_body.messages.iter().take(MAX_ALLOWED_MESSAGES) { + // Skip all messages in this transaction that are not Send messages. + if msg.type_url != *COSMOS_SDK_TRANSFER_MSG_URL.to_string() { + continue; + } + + // Parse a Send message and check that it has the required recipient. + let transfer_msg: MsgSend = MsgSend::decode(msg.value.as_slice())?; + if transfer_msg.to_address == recipient { + for coin in transfer_msg.amount { + deposits.push(Transfer { + sender: transfer_msg.from_address.clone(), + amount: coin.amount.clone(), + denom: coin.denom, + recipient: recipient.to_string(), + }); + } + } + } + Ok(deposits) +} + +/// sudo_kv_query_result is the contract's callback for KV query results. Note that only the query +/// id is provided, so you need to read the query result from the state. +pub fn sudo_kv_query_result( + deps: DepsMut, + _env: Env, + query_id: u64, +) -> StdResult> { + deps.api.debug( + format!( + "WASMDEBUG: sudo_kv_query_result received; query_id: {:?}", + query_id, + ) + .as_str(), + ); + Ok(Response::default()) +} + +pub fn register_transfers_query( + connection_id: String, + recipient: String, + update_period: u64, + min_height: Option, +) -> NeutronResult> { + let msg = + new_register_transfers_query_msg(connection_id, recipient, update_period, min_height)?; + + Ok(Response::new().add_message(msg)) +} diff --git a/contracts/testing/test-icq-lib/src/lib.rs b/contracts/testing/test-icq-lib/src/lib.rs new file mode 100644 index 00000000..e1a4621c --- /dev/null +++ b/contracts/testing/test-icq-lib/src/lib.rs @@ -0,0 +1,4 @@ +pub mod contract; +pub mod icq; +pub mod msg; +pub mod state; diff --git a/contracts/testing/test-icq-lib/src/msg.rs b/contracts/testing/test-icq-lib/src/msg.rs new file mode 100644 index 00000000..13870b96 --- /dev/null +++ b/contracts/testing/test-icq-lib/src/msg.rs @@ -0,0 +1,24 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; + +#[cw_serde] +pub struct InstantiateMsg {} + +#[cw_serde] +pub enum ExecuteMsg { + RegisterBalancesQuery { + connection_id: String, + update_period: u64, + addr: String, + denoms: Vec, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(neutron_sdk::interchain_queries::v047::queries::BalanceResponse)] + Balance { query_id: u64 }, +} + +#[cw_serde] +pub enum MigrateMsg {} diff --git a/contracts/testing/test-icq-lib/src/state.rs b/contracts/testing/test-icq-lib/src/state.rs new file mode 100644 index 00000000..452f7dd0 --- /dev/null +++ b/contracts/testing/test-icq-lib/src/state.rs @@ -0,0 +1,25 @@ +use cosmwasm_schema::cw_serde; +use cw_storage_plus::{Item, Map}; + +/// contains all transfers mapped by a recipient address observed by the contract. +pub const RECIPIENT_TXS: Map> = Map::new("recipient_txs"); +/// contains number of transfers to addresses observed by the contract. +pub const TRANSFERS: Item = Item::new("transfers"); + +#[cw_serde] +pub struct Transfer { + pub recipient: String, + pub sender: String, + pub denom: String, + pub amount: String, +} + +#[cw_serde] +pub struct OpenAckVersion { + pub version: String, + pub controller_connection_id: String, + pub host_connection_id: String, + pub address: String, + pub encoding: String, + pub tx_type: String, +} From 53b3419cd9f00cd734c589b366d2c76501c50293 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 25 Nov 2024 17:40:59 +0100 Subject: [PATCH 39/92] init local ic icq relayer --- local-interchaintest/src/utils/icq.rs | 71 +++++++++++++++++++++++++++ local-interchaintest/src/utils/mod.rs | 1 + 2 files changed, 72 insertions(+) create mode 100644 local-interchaintest/src/utils/icq.rs diff --git a/local-interchaintest/src/utils/icq.rs b/local-interchaintest/src/utils/icq.rs new file mode 100644 index 00000000..a8ededab --- /dev/null +++ b/local-interchaintest/src/utils/icq.rs @@ -0,0 +1,71 @@ +use std::{fs::File, io::Write, path::PathBuf}; + +use localic_utils::{utils::test_context::TestContext, NEUTRON_CHAIN_NAME}; + +pub fn generate_icq_relayer_config( + test_ctx: &TestContext, + current_path: PathBuf, + target_domain: String, +) -> std::io::Result<()> { + let target_connection_id = test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&target_domain) + .get(); + + // formatted according to neutron ICQ relayer docs + let target_chain_rpc = format!( + "tcp://local{}-1-val-0-neutron_gaia_junoic:26657", + target_domain + ); + let env_content = format!( + r#" +RELAYER_NEUTRON_CHAIN_RPC_ADDR={neutron_rpc} +RELAYER_NEUTRON_CHAIN_REST_ADDR={neutron_rest} +RELAYER_NEUTRON_CHAIN_HOME_DIR=/data +RELAYER_NEUTRON_CHAIN_SIGN_KEY_NAME=acc3 +RELAYER_NEUTRON_CHAIN_GAS_PRICES=0.5untrn +RELAYER_NEUTRON_CHAIN_GAS_LIMIT=10000000 +RELAYER_NEUTRON_CHAIN_GAS_ADJUSTMENT=1.3 +RELAYER_NEUTRON_CHAIN_DENOM=untrn +RELAYER_NEUTRON_CHAIN_MAX_GAS_PRICE=1000 +RELAYER_NEUTRON_CHAIN_GAS_PRICE_MULTIPLIER=3.0 +RELAYER_NEUTRON_CHAIN_CONNECTION_ID={connection_id} +RELAYER_NEUTRON_CHAIN_DEBUG=true +RELAYER_NEUTRON_CHAIN_KEYRING_BACKEND=test +RELAYER_NEUTRON_CHAIN_ACCOUNT_PREFIX=neutron +RELAYER_NEUTRON_CHAIN_KEY=acc3 +RELAYER_NEUTRON_CHAIN_OUTPUT_FORMAT=json +RELAYER_NEUTRON_CHAIN_SIGN_MODE_STR=direct + +RELAYER_TARGET_CHAIN_RPC_ADDR={target_rpc} +RELAYER_TARGET_CHAIN_TIMEOUT=10s +RELAYER_TARGET_CHAIN_DEBUG=true +RELAYER_TARGET_CHAIN_KEYRING_BACKEND=test +RELAYER_TARGET_CHAIN_OUTPUT_FORMAT=json + +RELAYER_REGISTRY_ADDRESSES= +RELAYER_REGISTRY_QUERY_IDS= + +RELAYER_ALLOW_TX_QUERIES=true +RELAYER_ALLOW_KV_CALLBACKS=true +RELAYER_STORAGE_PATH=storage/leveldb +RELAYER_WEBSERVER_PORT=127.0.0.1:9999 +RELAYER_IGNORE_ERRORS_REGEX=(execute wasm contract failed|failed to build tx query string) +"#, + neutron_rpc = "tcp://localneutron-1-val-0-neutron_gaia_junoic:26657", + neutron_rest = "http://localneutron-1-val-0-neutron_gaia_junoic:1317", + connection_id = target_connection_id, + target_rpc = target_chain_rpc, + ); + + // create the env file and write the dynamically generated config there + let path = current_path + .join("local-interchaintest") + .join("configs") + .join(".env"); + let mut file = File::create(path)?; + file.write_all(env_content.as_bytes())?; + + Ok(()) +} diff --git a/local-interchaintest/src/utils/mod.rs b/local-interchaintest/src/utils/mod.rs index d7a1a28d..1718ad9a 100644 --- a/local-interchaintest/src/utils/mod.rs +++ b/local-interchaintest/src/utils/mod.rs @@ -1,6 +1,7 @@ pub mod authorization; pub mod base_account; pub mod ibc; +pub mod icq; pub mod manager; pub mod osmosis; pub mod persistence; From c15ea130b5de9f8ffa109d974607fb78f5ff8783 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 11:13:53 +0100 Subject: [PATCH 40/92] starting icq-relayer --- Cargo.lock | 15 ++++ local-interchaintest/examples/icq_test.rs | 40 +++++++++++ local-interchaintest/src/utils/icq.rs | 84 ++++++++++++++++++++++- 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 local-interchaintest/examples/icq_test.rs diff --git a/Cargo.lock b/Cargo.lock index 7b14d388..f90c56e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5583,6 +5583,21 @@ dependencies = [ "valence-macros", ] +[[package]] +name = "valence-test-icq-lib" +version = "0.1.0" +dependencies = [ + "cosmos-sdk-proto 0.20.0", + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-storage-plus 2.0.0", + "cw2 2.0.0", + "neutron-sdk", + "serde-json-wasm 1.0.1", + "thiserror 1.0.69", + "valence-processor-utils", +] + [[package]] name = "valence-test-library" version = "0.1.0" diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs new file mode 100644 index 00000000..6eaa0c85 --- /dev/null +++ b/local-interchaintest/examples/icq_test.rs @@ -0,0 +1,40 @@ +use local_interchaintest::utils::{ + icq::{generate_icq_relayer_config, start_icq_relayer}, + LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, +}; +use std::{env, error::Error}; + +use localic_utils::{ + ConfigChainBuilder, TestContextBuilder, LOCAL_IC_API_URL, NEUTRON_CHAIN_NAME, + OSMOSIS_CHAIN_NAME, +}; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let mut test_ctx = TestContextBuilder::default() + .with_unwrap_raw_logs(true) + .with_api_url(LOCAL_IC_API_URL) + .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) + .with_chain(ConfigChainBuilder::default_neutron().build()?) + .with_chain(ConfigChainBuilder::default_osmosis().build()?) + .with_chain(ConfigChainBuilder::default_gaia().build()?) + .with_log_file_path(LOGS_FILE_PATH) + .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) + .build()?; + + let current_dir = env::current_dir()?; + + // with test context set up, we can generate the .env file for the icq relayer + generate_icq_relayer_config( + &test_ctx, + current_dir.clone(), + OSMOSIS_CHAIN_NAME.to_string(), + )?; + + // start the icq relayer. this runs in detached mode so we need + // to manually kill it before each run for now. + start_icq_relayer()?; + + Ok(()) +} diff --git a/local-interchaintest/src/utils/icq.rs b/local-interchaintest/src/utils/icq.rs index a8ededab..574e220e 100644 --- a/local-interchaintest/src/utils/icq.rs +++ b/local-interchaintest/src/utils/icq.rs @@ -1,6 +1,7 @@ use std::{fs::File, io::Write, path::PathBuf}; use localic_utils::{utils::test_context::TestContext, NEUTRON_CHAIN_NAME}; +use log::info; pub fn generate_icq_relayer_config( test_ctx: &TestContext, @@ -15,7 +16,7 @@ pub fn generate_icq_relayer_config( // formatted according to neutron ICQ relayer docs let target_chain_rpc = format!( - "tcp://local{}-1-val-0-neutron_gaia_junoic:26657", + "tcp://local{}-1-val-0-neutron_osmosisic:26657", target_domain ); let env_content = format!( @@ -53,8 +54,8 @@ RELAYER_STORAGE_PATH=storage/leveldb RELAYER_WEBSERVER_PORT=127.0.0.1:9999 RELAYER_IGNORE_ERRORS_REGEX=(execute wasm contract failed|failed to build tx query string) "#, - neutron_rpc = "tcp://localneutron-1-val-0-neutron_gaia_junoic:26657", - neutron_rest = "http://localneutron-1-val-0-neutron_gaia_junoic:1317", + neutron_rpc = "tcp://localneutron-1-val-0-neutron_osmosisic:26657", + neutron_rest = "http://localneutron-1-val-0-neutron_osmosisic:1317", connection_id = target_connection_id, target_rpc = target_chain_rpc, ); @@ -69,3 +70,80 @@ RELAYER_IGNORE_ERRORS_REGEX=(execute wasm contract failed|failed to build tx que Ok(()) } + +pub fn start_icq_relayer() -> Result<(), Box> { + // match std::process::Command::new("docker") + // .arg("inspect") + // .arg("icq-relayer") + // .output() + // { + // Ok(r) => { + // info!("ICQ relayer already running: {:?}", r); + // return Ok(()); + // } + // Err(e) => info!("inspect icq relayer error: {:?}", e), + // }; + // First try to stop and remove any existing icq-relayer container + let _ = std::process::Command::new("docker") + .arg("stop") + .arg("icq-relayer") + .output(); + let _ = std::process::Command::new("docker") + .arg("rm") + .arg("icq-relayer") + .output(); + + let output = std::process::Command::new("docker") + .arg("inspect") + .arg("localneutron-1-val-0-neutron_osmosisic") + .output() + .expect("failed to inspect the neutron container"); + + let stdout = String::from_utf8_lossy(&output.stdout); + let response: serde_json::Value = + serde_json::from_str(&stdout).expect("Failed to parse JSON from docker inspect output"); + + // extract the docker network under which neutron container is spinning + let docker_network = response[0]["NetworkSettings"]["Networks"].clone(); + let network_name = docker_network + .as_object() + .unwrap() + .keys() + .next() + .unwrap() + .to_string(); + + // extract the mount point of neutron chain on host machine + let mount_point = response[0]["Mounts"][0]["Source"].as_str().unwrap(); + + // this should be initiated by `just local-ic-run`, so we know the relpath + let env_relpath = "local-interchaintest/configs/.env"; + + let start_icq_relayer_cmd = std::process::Command::new("docker") + .arg("run") + .arg("-d") // detached mode to not block the main() + .arg("--name") + .arg("icq-relayer") + .arg("--env-file") + .arg(env_relpath) // passing the .env file we generated before + .arg("-p") + .arg("9999:9999") // the port binding for the relayer webserver, idk if it's needed + .arg("--network") + .arg(network_name) // docker network under which we want to run the relayer + .arg("-v") + .arg(format!("{}:/data", mount_point)) // neutron mount point to access the keyring + .arg("neutron-org/neutron-query-relayer") + .output() + .expect("failed to start icq relayer"); + + if start_icq_relayer_cmd.status.success() { + let container_id = String::from_utf8_lossy(&start_icq_relayer_cmd.stdout) + .trim() + .to_string(); + info!("ICQ relayer container started with ID: {container_id}"); + Ok(()) + } else { + let error = String::from_utf8_lossy(&start_icq_relayer_cmd.stderr); + Err(format!("Failed to start ICQ relayer: {error}").into()) + } +} From 7e4fc32841c7f55760f36d39a93a0237b6a8a61c Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 11:44:44 +0100 Subject: [PATCH 41/92] instantiating icq test lib on icq_test --- Cargo.lock | 3 ++ contracts/testing/test-icq-lib/Cargo.toml | 9 +++- .../testing/test-icq-lib/src/contract.rs | 30 ++++-------- contracts/testing/test-icq-lib/src/msg.rs | 3 +- local-interchaintest/Cargo.toml | 1 + local-interchaintest/examples/icq_test.rs | 46 ++++++++++++++++++- 6 files changed, 67 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f90c56e3..fda0944a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2580,6 +2580,7 @@ dependencies = [ "valence-program-registry-utils", "valence-reverse-splitter-library", "valence-splitter-library", + "valence-test-icq-lib", ] [[package]] @@ -5593,7 +5594,9 @@ dependencies = [ "cw-storage-plus 2.0.0", "cw2 2.0.0", "neutron-sdk", + "schemars", "serde-json-wasm 1.0.1", + "serde_json", "thiserror 1.0.69", "valence-processor-utils", ] diff --git a/contracts/testing/test-icq-lib/Cargo.toml b/contracts/testing/test-icq-lib/Cargo.toml index d8fd2158..c96c3450 100644 --- a/contracts/testing/test-icq-lib/Cargo.toml +++ b/contracts/testing/test-icq-lib/Cargo.toml @@ -13,7 +13,12 @@ crate-type = ["cdylib", "rlib"] library = [] [dependencies] -cosmwasm-std = { workspace = true } +# cosmwasm-std = { workspace = true } +cosmwasm-std = { version = "2.1.3", features = [ + "cosmwasm_1_1", + "cosmwasm_1_2", + "cosmwasm_1_4", +] } cosmwasm-schema = { workspace = true } cw-storage-plus = { workspace = true } thiserror = { workspace = true } @@ -22,3 +27,5 @@ neutron-sdk = { workspace = true } serde-json-wasm = "1.0.0" cw2 = { workspace = true } cosmos-sdk-proto = { workspace = true } +schemars = { workspace = true } +serde_json = { workspace = true } diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index eccf3ad3..64bd6d00 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -1,7 +1,6 @@ use crate::icq; use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; use crate::state::OpenAckVersion; -use crate::state::{RECIPIENT_TXS, TRANSFERS}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ @@ -15,13 +14,13 @@ use neutron_sdk::{ NeutronResult, }; -pub const CONTRACT_NAME: &str = "orbital-core"; +pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub type QueryDeps<'a> = Deps<'a, NeutronQuery>; pub type ExecuteDeps<'a> = DepsMut<'a, NeutronQuery>; -#[entry_point] +#[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: ExecuteDeps, _env: Env, @@ -32,7 +31,7 @@ pub fn instantiate( Ok(Response::new()) } -#[entry_point] +#[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( deps: ExecuteDeps, env: Env, @@ -49,7 +48,7 @@ pub fn execute( } } -#[entry_point] +#[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: QueryDeps, env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::Balance { query_id } => to_json_binary(&query_icq_balance(deps, env, query_id)?), @@ -60,18 +59,18 @@ fn query_icq_balance(deps: QueryDeps, env: Env, query_id: u64) -> StdResult StdResult> { - unimplemented!() + Ok(Response::default()) } -#[entry_point] +#[cfg_attr(not(feature = "library"), entry_point)] pub fn migrate(_deps: ExecuteDeps, _env: Env, _msg: MigrateMsg) -> StdResult> { - unimplemented!() + Ok(Response::default()) } // neutron uses the `sudo` entry point in their ICA/ICQ related logic -#[entry_point] +#[cfg_attr(not(feature = "library"), entry_point)] pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult> { match msg { // For handling successful registering of ICA @@ -115,16 +114,5 @@ fn sudo_open_ack( serde_json_wasm::from_str(counterparty_version.as_str()) .map_err(|_| StdError::generic_err("Can't parse counterparty_version"))?; - // // extract the ICA identifier from the port - // let ica_identifier = extract_ica_identifier_from_port(port_id)?; - - // let clearing_account_config = ClearingAccountConfig { - // addr: parsed_version.address, - // controller_connection_id: parsed_version.controller_connection_id, - // }; - - // // Update the storage record associated with the interchain account. - // CLEARING_ACCOUNTS.save(deps.storage, ica_identifier, &Some(clearing_account_config))?; - Ok(Response::default()) } diff --git a/contracts/testing/test-icq-lib/src/msg.rs b/contracts/testing/test-icq-lib/src/msg.rs index 13870b96..6c16fc08 100644 --- a/contracts/testing/test-icq-lib/src/msg.rs +++ b/contracts/testing/test-icq-lib/src/msg.rs @@ -1,4 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use neutron_sdk::interchain_queries::v047::queries::BalanceResponse; #[cw_serde] pub struct InstantiateMsg {} @@ -16,7 +17,7 @@ pub enum ExecuteMsg { #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { - #[returns(neutron_sdk::interchain_queries::v047::queries::BalanceResponse)] + #[returns(BalanceResponse)] Balance { query_id: u64 }, } diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 65dc81d8..dd6feb8a 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -45,3 +45,4 @@ valence-osmosis-cl-withdrawer = { workspace = true } valence-osmosis-utils = { workspace = true } tokio = { workspace = true } osmosis-std = { workspace = true } +valence-test-icq-lib = { workspace = true } diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index 6eaa0c85..fed06a29 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -2,10 +2,13 @@ use local_interchaintest::utils::{ icq::{generate_icq_relayer_config, start_icq_relayer}, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, }; -use std::{env, error::Error}; +use localic_std::modules::cosmwasm::contract_instantiate; +use log::info; +use std::{env, error::Error, time::Duration}; +use valence_test_icq_lib::msg::InstantiateMsg; use localic_utils::{ - ConfigChainBuilder, TestContextBuilder, LOCAL_IC_API_URL, NEUTRON_CHAIN_NAME, + ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, LOCAL_IC_API_URL, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME, }; @@ -36,5 +39,44 @@ fn main() -> Result<(), Box> { // to manually kill it before each run for now. start_icq_relayer()?; + let mut uploader = test_ctx.build_tx_upload_contracts(); + let icq_test_lib_local_path = format!( + "{}/artifacts/valence_test_icq_lib.wasm", + current_dir.display() + ); + + info!("sleeping to allow icq relayer to start..."); + std::thread::sleep(Duration::from_secs(10)); + + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&icq_test_lib_local_path)?; + + let icq_test_lib_code_id = test_ctx + .get_contract() + .contract("valence_test_icq_lib") + .get_cw() + .code_id + .unwrap(); + + info!("icq test lib code id: {icq_test_lib_code_id}"); + + let icq_lib_instantiate_msg = InstantiateMsg {}; + + // instantiate icq test lib + let icq_test_lib = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + icq_test_lib_code_id, + &serde_json::to_string(&icq_lib_instantiate_msg)?, + "valence_test_icq_lib", + None, + "", + )?; + + info!("icq test lib: {}", icq_test_lib.address); + Ok(()) } From f66436e84f8ef2f30578509c1d7338b7c227f29c Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 12:23:46 +0100 Subject: [PATCH 42/92] balance queries working --- Cargo.lock | 1 + .../testing/test-icq-lib/src/contract.rs | 12 +-- local-interchaintest/Cargo.toml | 1 + local-interchaintest/examples/icq_test.rs | 86 ++++++++++++++++++- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fda0944a..3cf0eb5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2550,6 +2550,7 @@ dependencies = [ "localic-std", "localic-utils", "log", + "neutron-sdk", "osmosis-std", "persistence-std", "polytone-note", diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index 64bd6d00..a4624543 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -25,7 +25,7 @@ pub fn instantiate( deps: ExecuteDeps, _env: Env, _info: MessageInfo, - msg: InstantiateMsg, + _msg: InstantiateMsg, ) -> NeutronResult> { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; Ok(Response::new()) @@ -33,9 +33,9 @@ pub fn instantiate( #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( - deps: ExecuteDeps, - env: Env, - info: MessageInfo, + _deps: ExecuteDeps, + _env: Env, + _info: MessageInfo, msg: ExecuteMsg, ) -> NeutronResult> { match msg { @@ -102,9 +102,9 @@ pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult Result<(), Box> { info!("icq test lib: {}", icq_test_lib.address); + let icq_registration_response = register_icq_balances_query( + &test_ctx, + icq_test_lib.address.to_string(), + OSMOSIS_CHAIN_NAME.to_string(), + OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + vec![OSMOSIS_CHAIN_DENOM.to_string()], + )?; + + info!("icq registration response: {:?}", icq_registration_response); + + for _ in 0..10 { + let response_value = + query_balance_query_id(&test_ctx, icq_test_lib.address.to_string(), 1)?; + + info!("response value: {:?}", response_value); + std::thread::sleep(Duration::from_secs(5)); + } + Ok(()) } + +pub fn register_icq_balances_query( + test_ctx: &TestContext, + icq_lib: String, + domain: String, + addr: String, + denoms: Vec, +) -> Result { + info!("registering ICQ balances query on domain {domain} for {addr}..."); + + let register_icq_msg = ExecuteMsg::RegisterBalancesQuery { + connection_id: test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&domain) + .get(), + update_period: 5, + addr, + denoms, + }; + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &serde_json::to_string(®ister_icq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + "--amount 1000000untrn --gas 50000000", + ) +} + +pub fn query_balance_query_id( + test_ctx: &TestContext, + icq_lib: String, + query_id: u64, +) -> Result { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::Balance { query_id }) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let balance_response: neutron_sdk::interchain_queries::v047::queries::BalanceResponse = + serde_json::from_value(query_response).unwrap(); + + info!("balance query response: {:?}", balance_response); + + Ok(balance_response) +} From 8839dd71bdb6094bdea4403e0dade51810bda746 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 14:33:58 +0100 Subject: [PATCH 43/92] querying raw kv storagevalue results --- Cargo.lock | 8 + contracts/testing/test-icq-lib/Cargo.toml | 1 + .../testing/test-icq-lib/src/contract.rs | 77 ++++++++- contracts/testing/test-icq-lib/src/icq.rs | 43 ++++- contracts/testing/test-icq-lib/src/msg.rs | 14 +- contracts/testing/test-icq-lib/src/state.rs | 2 + local-interchaintest/Cargo.toml | 1 + local-interchaintest/examples/icq_test.rs | 160 +++++++++++++++++- 8 files changed, 294 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3cf0eb5d..5cf1513d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,6 +384,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -2541,6 +2547,7 @@ checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" name = "local-interchaintest" version = "0.1.0" dependencies = [ + "base64 0.13.1", "cosmos-grpc-client", "cosmwasm-std 1.5.8", "cosmwasm-std 2.1.4", @@ -5596,6 +5603,7 @@ dependencies = [ "cw2 2.0.0", "neutron-sdk", "schemars", + "serde", "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", diff --git a/contracts/testing/test-icq-lib/Cargo.toml b/contracts/testing/test-icq-lib/Cargo.toml index c96c3450..c248bd45 100644 --- a/contracts/testing/test-icq-lib/Cargo.toml +++ b/contracts/testing/test-icq-lib/Cargo.toml @@ -29,3 +29,4 @@ cw2 = { workspace = true } cosmos-sdk-proto = { workspace = true } schemars = { workspace = true } serde_json = { workspace = true } +serde = { workspace = true } diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index a4624543..f40a178a 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -1,18 +1,27 @@ use crate::icq; use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; -use crate::state::OpenAckVersion; +use crate::state::{OpenAckVersion, CATCHALL}; +use cosmos_sdk_proto::cosmos::base::abci::v1beta1::TxMsgData; +use cosmos_sdk_proto::prost::Message; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, + attr, to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, + StdError, StdResult, }; use cw2::set_contract_version; +use cw_storage_plus::KeyDeserialize; +use neutron_sdk::interchain_queries::queries::get_raw_interchain_query_result; +use neutron_sdk::interchain_txs::helpers::decode_message_response; +use neutron_sdk::sudo::msg::RequestPacket; +use neutron_sdk::NeutronError; use neutron_sdk::{ bindings::{msg::NeutronMsg, query::NeutronQuery}, interchain_queries::v047::queries::{query_balance, BalanceResponse}, sudo::msg::SudoMsg, NeutronResult, }; +use serde_json::value::Serializer; pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -45,6 +54,11 @@ pub fn execute( addr, denoms, } => icq::register_balances_query(connection_id, addr, denoms, update_period), + ExecuteMsg::RegisterKeyValueQuery { + connection_id, + update_period, + key, + } => icq::register_kv_query(connection_id, update_period, key), } } @@ -52,6 +66,19 @@ pub fn execute( pub fn query(deps: QueryDeps, env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::Balance { query_id } => to_json_binary(&query_icq_balance(deps, env, query_id)?), + QueryMsg::Catchall {} => { + let mut resp: Vec<(String, String)> = vec![]; + for e in CATCHALL.range(deps.storage, None, None, cosmwasm_std::Order::Ascending) { + resp.push(e?); + } + + to_json_binary(&resp) + } + QueryMsg::RawIcqResult { id } => { + let resp = get_raw_interchain_query_result(deps, id) + .map_err(|e| StdError::generic_err(e.to_string()))?; + to_json_binary(&resp.result) + } } } @@ -96,15 +123,53 @@ pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult icq::sudo_kv_query_result(deps, env, query_id), - _ => Ok(Response::default()), + SudoMsg::Response { request, data } => sudo_response(deps, env, request, data), + _ => { + let k = "sudo_catchall_handler".to_string(); + let v = to_json_string(&msg)?; + CATCHALL.save(deps.storage, k, &v)?; + Ok(Response::default()) + } + } +} + +fn sudo_response( + deps: DepsMut, + _env: Env, + request: RequestPacket, + data: Binary, +) -> StdResult> { + let _seq_id = request + .sequence + .ok_or_else(|| StdError::generic_err("sequence not found"))?; + + let msg_data: TxMsgData = + TxMsgData::decode(data.as_slice()).map_err(|e| StdError::generic_err(e.to_string()))?; + deps.api + .debug(&format!("WASMDEBUG: msg_data: data: {msg_data:?}")); + + #[allow(deprecated)] + for item in msg_data.data { + // let resp = decode_message_response(&item.data); + // let (k, v) = match serde_json::to_value(&item) { + // Ok(val) => , + // Err(e) => todo!(), + // }; + let k = to_json_string(&request)?; + // let v = to_json_string(&item)?; + let v = String::from_vec(item.data.to_ascii_lowercase())?; + + CATCHALL.save(deps.storage, k, &v)?; } + + Ok(Response::default()) } // handler fn sudo_open_ack( - _deps: ExecuteDeps, + deps: ExecuteDeps, _env: Env, - _port_id: String, + port_id: String, _channel_id: String, _counterparty_channel_id: String, counterparty_version: String, @@ -114,5 +179,7 @@ fn sudo_open_ack( serde_json_wasm::from_str(counterparty_version.as_str()) .map_err(|_| StdError::generic_err("Can't parse counterparty_version"))?; + CATCHALL.save(deps.storage, "sudo_open_ack".to_string(), &port_id)?; + Ok(Response::default()) } diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index f9404922..8496d287 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -7,10 +7,24 @@ use cosmos_sdk_proto::{ }; use cosmwasm_std::{Binary, DepsMut, Env, Response}; use neutron_sdk::{ - bindings::{msg::NeutronMsg, query::NeutronQuery, types::Height}, + bindings::{ + msg::NeutronMsg, + query::NeutronQuery, + types::{Height, KVKey}, + }, interchain_queries::{ get_registered_query, - v045::{new_register_balances_query_msg, new_register_transfers_query_msg}, + helpers::decode_and_convert, + types::QueryPayload, + v045::{ + new_register_balances_query_msg, new_register_distribution_fee_pool_query_msg, + new_register_transfers_query_msg, + }, + v047::{ + helpers::create_account_denom_balance_key, + register_queries::new_register_delegator_delegations_query_msg, + types::{BANK_STORE_KEY, DISTRIBUTION_STORE_KEY, SUPPLY_PREFIX}, + }, }, NeutronResult, }; @@ -167,3 +181,28 @@ pub fn register_transfers_query( Ok(Response::new().add_message(msg)) } + +pub fn register_kv_query( + connection_id: String, + update_period: u64, + key: String, +) -> NeutronResult> { + let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; + + let converted_addr_bytes = decode_and_convert(&addr)?; + + let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo")?; + + let kv_key = KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }; + + let msg = NeutronMsg::register_interchain_query( + QueryPayload::KV(vec![kv_key]), + connection_id, + update_period, + )?; + + Ok(Response::new().add_message(msg)) +} diff --git a/contracts/testing/test-icq-lib/src/msg.rs b/contracts/testing/test-icq-lib/src/msg.rs index 6c16fc08..66ceb8d2 100644 --- a/contracts/testing/test-icq-lib/src/msg.rs +++ b/contracts/testing/test-icq-lib/src/msg.rs @@ -1,5 +1,8 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use neutron_sdk::interchain_queries::v047::queries::BalanceResponse; +use neutron_sdk::{ + bindings::types::InterchainQueryResult, interchain_queries::v047::queries::BalanceResponse, + proto_types::neutron::interchainqueries::QueryResult, +}; #[cw_serde] pub struct InstantiateMsg {} @@ -12,6 +15,11 @@ pub enum ExecuteMsg { addr: String, denoms: Vec, }, + RegisterKeyValueQuery { + connection_id: String, + update_period: u64, + key: String, + }, } #[cw_serde] @@ -19,6 +27,10 @@ pub enum ExecuteMsg { pub enum QueryMsg { #[returns(BalanceResponse)] Balance { query_id: u64 }, + #[returns(Vec<(String, String)>)] + Catchall {}, + #[returns(InterchainQueryResult)] + RawIcqResult { id: u64 }, } #[cw_serde] diff --git a/contracts/testing/test-icq-lib/src/state.rs b/contracts/testing/test-icq-lib/src/state.rs index 452f7dd0..5bd9e38e 100644 --- a/contracts/testing/test-icq-lib/src/state.rs +++ b/contracts/testing/test-icq-lib/src/state.rs @@ -6,6 +6,8 @@ pub const RECIPIENT_TXS: Map> = Map::new("recipient_txs"); /// contains number of transfers to addresses observed by the contract. pub const TRANSFERS: Item = Item::new("transfers"); +pub const CATCHALL: Map = Map::new("catchall"); + #[cw_serde] pub struct Transfer { pub recipient: String, diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index acbdd485..bb0f67ff 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -47,3 +47,4 @@ tokio = { workspace = true } osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } +base64 = "0.13.0" diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index 0848ce18..389b78d7 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -8,6 +8,8 @@ use localic_std::{ types::TransactionResponse, }; use log::info; +use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; +use serde_json::Value; use std::{env, error::Error, time::Duration}; use valence_test_icq_lib::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -66,8 +68,6 @@ fn main() -> Result<(), Box> { info!("icq test lib code id: {icq_test_lib_code_id}"); - let icq_lib_instantiate_msg = InstantiateMsg {}; - // instantiate icq test lib let icq_test_lib = contract_instantiate( test_ctx @@ -75,7 +75,7 @@ fn main() -> Result<(), Box> { .get_request_builder(NEUTRON_CHAIN_NAME), DEFAULT_KEY, icq_test_lib_code_id, - &serde_json::to_string(&icq_lib_instantiate_msg)?, + &serde_json::to_string(&InstantiateMsg {})?, "valence_test_icq_lib", None, "", @@ -98,12 +98,123 @@ fn main() -> Result<(), Box> { query_balance_query_id(&test_ctx, icq_test_lib.address.to_string(), 1)?; info!("response value: {:?}", response_value); - std::thread::sleep(Duration::from_secs(5)); + + if !response_value.balances.coins.is_empty() { + break; + } else { + std::thread::sleep(Duration::from_secs(5)); + } + } + + std::thread::sleep(Duration::from_secs(3)); + let kvq_registration_response = register_kvq_balances_query( + &test_ctx, + icq_test_lib.address.to_string(), + OSMOSIS_CHAIN_NAME.to_string(), + OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + )?; + + info!( + "kv query registration response: {:?}", + kvq_registration_response + ); + + for _ in 0..10 { + let response_value = query_catchall_logs(&test_ctx, icq_test_lib.address.to_string())?; + info!("catchall logs: {:?}", response_value); + + let raw_query_resp = query_raw_result(&test_ctx, icq_test_lib.address.to_string(), 1)?; + info!("raw query response: {:?}", raw_query_resp); + + for kv_result in raw_query_resp.kv_results { + // let key = kv_result.key; + // let value = kv_result.value; + + let parse_attempt = try_parse_storage_value(&kv_result); + + info!("\nPARSE ATTEMPT: {:?}", parse_attempt); + } + + if !response_value.is_empty() { + break; + } else { + std::thread::sleep(Duration::from_secs(5)); + } } Ok(()) } +fn try_parse_storage_value(storage_value: &StorageValue) -> Value { + let mut map = serde_json::Map::new(); + + // Add storage prefix + map.insert( + "storage_prefix".to_string(), + Value::String(storage_value.storage_prefix.clone()), + ); + + // Try UTF-8 string interpretation + if let Ok(key_str) = String::from_utf8(storage_value.key.to_vec()) { + map.insert("key_utf8".to_string(), Value::String(key_str)); + } + + if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { + map.insert("value_utf8".to_string(), Value::String(value_str)); + } + + // Try JSON interpretation + if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { + if let Ok(json_value) = serde_json::from_str(&value_str) { + map.insert("value_json".to_string(), json_value); + } + } + + if let Ok(value_str) = String::from_utf8(storage_value.key.to_vec()) { + if let Ok(json_value) = serde_json::from_str(&value_str) { + map.insert("key_json".to_string(), json_value); + } + } + + // Convert raw bytes to base64 + map.insert( + "key".to_string(), + Value::String(storage_value.key.to_string()), + ); + + Value::Object(map) +} + +fn register_kvq_balances_query( + test_ctx: &TestContext, + icq_lib: String, + domain: String, + addr: String, +) -> Result { + info!("registering ICQ KV query on domain {domain}..."); + + let register_kvq_msg = ExecuteMsg::RegisterKeyValueQuery { + connection_id: test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&domain) + .get(), + update_period: 5, + key: addr, + }; + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &serde_json::to_string(®ister_kvq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + "--amount 1000000untrn --gas 50000000", + ) +} + pub fn register_icq_balances_query( test_ctx: &TestContext, icq_lib: String, @@ -158,3 +269,44 @@ pub fn query_balance_query_id( Ok(balance_response) } + +pub fn query_raw_result( + test_ctx: &TestContext, + icq_lib: String, + query_id: u64, +) -> Result { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::RawIcqResult { id: query_id }) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let icq_result: InterchainQueryResult = serde_json::from_value(query_response).unwrap(); + + info!("raw icq result: {:?}", icq_result); + + Ok(icq_result) +} + +pub fn query_catchall_logs( + test_ctx: &TestContext, + icq_lib: String, +) -> Result, LocalError> { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::Catchall {}) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let resp: Vec<(String, String)> = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} From 6f47458303d961f3f7c92772b6472f59ea033ddd Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 15:07:28 +0100 Subject: [PATCH 44/92] cleanup & generalize contract msg --- .../testing/test-icq-lib/src/contract.rs | 3 +- contracts/testing/test-icq-lib/src/icq.rs | 13 +- contracts/testing/test-icq-lib/src/msg.rs | 3 +- local-interchaintest/examples/icq_test.rs | 233 ++++-------------- local-interchaintest/src/utils/icq.rs | 178 ++++++++++++- 5 files changed, 230 insertions(+), 200 deletions(-) diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index f40a178a..8893702f 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -57,8 +57,9 @@ pub fn execute( ExecuteMsg::RegisterKeyValueQuery { connection_id, update_period, + path, key, - } => icq::register_kv_query(connection_id, update_period, key), + } => icq::register_kv_query(connection_id, update_period, path, key), } } diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index 8496d287..5b582890 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -185,17 +185,12 @@ pub fn register_transfers_query( pub fn register_kv_query( connection_id: String, update_period: u64, - key: String, + path: String, + key: Vec, ) -> NeutronResult> { - let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; - - let converted_addr_bytes = decode_and_convert(&addr)?; - - let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo")?; - let kv_key = KVKey { - path: BANK_STORE_KEY.to_string(), - key: Binary::new(balance_key), + path, + key: Binary::new(key), }; let msg = NeutronMsg::register_interchain_query( diff --git a/contracts/testing/test-icq-lib/src/msg.rs b/contracts/testing/test-icq-lib/src/msg.rs index 66ceb8d2..92fb3f23 100644 --- a/contracts/testing/test-icq-lib/src/msg.rs +++ b/contracts/testing/test-icq-lib/src/msg.rs @@ -18,7 +18,8 @@ pub enum ExecuteMsg { RegisterKeyValueQuery { connection_id: String, update_period: u64, - key: String, + path: String, + key: Vec, }, } diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index 389b78d7..1b5b5f7c 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -1,5 +1,8 @@ use local_interchaintest::utils::{ - icq::{generate_icq_relayer_config, start_icq_relayer}, + icq::{ + generate_icq_relayer_config, query_catchall_logs, query_raw_result, + register_kvq_balances_query, start_icq_relayer, try_parse_storage_value, + }, GAS_FLAGS, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, }; use localic_std::{ @@ -8,7 +11,13 @@ use localic_std::{ types::TransactionResponse, }; use log::info; -use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; +use neutron_sdk::{ + bindings::types::{InterchainQueryResult, StorageValue}, + interchain_queries::{ + helpers::decode_and_convert, + v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, + }, +}; use serde_json::Value; use std::{env, error::Error, time::Duration}; use valence_test_icq_lib::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -19,6 +28,13 @@ use localic_utils::{ OSMOSIS_CHAIN_NAME, }; +// KeyNextGlobalPoolId defines key to store the next Pool ID to be used. +pub const NEXT_GLOBAL_POOL_ID_KEY: u8 = 0x01; +pub const PREFIX_POOLS_KEY: u8 = 0x02; +pub const TOTAL_LIQUIDITY_KEY: u8 = 0x03; +pub const PREFIX_MIGRATION_INFO_BALANCER_POOL_KEY: u8 = 0x04; +pub const GAMM_STORE_KEY: &str = "gamm"; + fn main() -> Result<(), Box> { env_logger::init(); @@ -83,35 +99,42 @@ fn main() -> Result<(), Box> { info!("icq test lib: {}", icq_test_lib.address); - let icq_registration_response = register_icq_balances_query( - &test_ctx, - icq_test_lib.address.to_string(), - OSMOSIS_CHAIN_NAME.to_string(), - OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), - vec![OSMOSIS_CHAIN_DENOM.to_string()], - )?; + // let icq_registration_response = register_icq_balances_query( + // &test_ctx, + // icq_test_lib.address.to_string(), + // OSMOSIS_CHAIN_NAME.to_string(), + // OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + // vec![OSMOSIS_CHAIN_DENOM.to_string()], + // )?; - info!("icq registration response: {:?}", icq_registration_response); + // info!("icq registration response: {:?}", icq_registration_response); - for _ in 0..10 { - let response_value = - query_balance_query_id(&test_ctx, icq_test_lib.address.to_string(), 1)?; + // for _ in 0..10 { + // let response_value = + // query_balance_query_id(&test_ctx, icq_test_lib.address.to_string(), 1)?; - info!("response value: {:?}", response_value); + // info!("response value: {:?}", response_value); - if !response_value.balances.coins.is_empty() { - break; - } else { - std::thread::sleep(Duration::from_secs(5)); - } - } + // if !response_value.balances.coins.is_empty() { + // break; + // } else { + // std::thread::sleep(Duration::from_secs(5)); + // } + // } std::thread::sleep(Duration::from_secs(3)); + let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; + + let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + + let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); + let kvq_registration_response = register_kvq_balances_query( &test_ctx, icq_test_lib.address.to_string(), OSMOSIS_CHAIN_NAME.to_string(), - OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + BANK_STORE_KEY.to_string(), + balance_key, )?; info!( @@ -119,7 +142,7 @@ fn main() -> Result<(), Box> { kvq_registration_response ); - for _ in 0..10 { + for _ in 0..2 { let response_value = query_catchall_logs(&test_ctx, icq_test_lib.address.to_string())?; info!("catchall logs: {:?}", response_value); @@ -144,169 +167,3 @@ fn main() -> Result<(), Box> { Ok(()) } - -fn try_parse_storage_value(storage_value: &StorageValue) -> Value { - let mut map = serde_json::Map::new(); - - // Add storage prefix - map.insert( - "storage_prefix".to_string(), - Value::String(storage_value.storage_prefix.clone()), - ); - - // Try UTF-8 string interpretation - if let Ok(key_str) = String::from_utf8(storage_value.key.to_vec()) { - map.insert("key_utf8".to_string(), Value::String(key_str)); - } - - if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { - map.insert("value_utf8".to_string(), Value::String(value_str)); - } - - // Try JSON interpretation - if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { - if let Ok(json_value) = serde_json::from_str(&value_str) { - map.insert("value_json".to_string(), json_value); - } - } - - if let Ok(value_str) = String::from_utf8(storage_value.key.to_vec()) { - if let Ok(json_value) = serde_json::from_str(&value_str) { - map.insert("key_json".to_string(), json_value); - } - } - - // Convert raw bytes to base64 - map.insert( - "key".to_string(), - Value::String(storage_value.key.to_string()), - ); - - Value::Object(map) -} - -fn register_kvq_balances_query( - test_ctx: &TestContext, - icq_lib: String, - domain: String, - addr: String, -) -> Result { - info!("registering ICQ KV query on domain {domain}..."); - - let register_kvq_msg = ExecuteMsg::RegisterKeyValueQuery { - connection_id: test_ctx - .get_connections() - .src(NEUTRON_CHAIN_NAME) - .dest(&domain) - .get(), - update_period: 5, - key: addr, - }; - - contract_execute( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - DEFAULT_KEY, - &serde_json::to_string(®ister_kvq_msg) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - "--amount 1000000untrn --gas 50000000", - ) -} - -pub fn register_icq_balances_query( - test_ctx: &TestContext, - icq_lib: String, - domain: String, - addr: String, - denoms: Vec, -) -> Result { - info!("registering ICQ balances query on domain {domain} for {addr}..."); - - let register_icq_msg = ExecuteMsg::RegisterBalancesQuery { - connection_id: test_ctx - .get_connections() - .src(NEUTRON_CHAIN_NAME) - .dest(&domain) - .get(), - update_period: 5, - addr, - denoms, - }; - - contract_execute( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - DEFAULT_KEY, - &serde_json::to_string(®ister_icq_msg) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - "--amount 1000000untrn --gas 50000000", - ) -} - -pub fn query_balance_query_id( - test_ctx: &TestContext, - icq_lib: String, - query_id: u64, -) -> Result { - let query_response = contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - &serde_json::to_string(&QueryMsg::Balance { query_id }) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - )["data"] - .clone(); - - let balance_response: neutron_sdk::interchain_queries::v047::queries::BalanceResponse = - serde_json::from_value(query_response).unwrap(); - - info!("balance query response: {:?}", balance_response); - - Ok(balance_response) -} - -pub fn query_raw_result( - test_ctx: &TestContext, - icq_lib: String, - query_id: u64, -) -> Result { - let query_response = contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - &serde_json::to_string(&QueryMsg::RawIcqResult { id: query_id }) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - )["data"] - .clone(); - - let icq_result: InterchainQueryResult = serde_json::from_value(query_response).unwrap(); - - info!("raw icq result: {:?}", icq_result); - - Ok(icq_result) -} - -pub fn query_catchall_logs( - test_ctx: &TestContext, - icq_lib: String, -) -> Result, LocalError> { - let query_response = contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - &serde_json::to_string(&QueryMsg::Catchall {}) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - )["data"] - .clone(); - - let resp: Vec<(String, String)> = serde_json::from_value(query_response).unwrap(); - - Ok(resp) -} diff --git a/local-interchaintest/src/utils/icq.rs b/local-interchaintest/src/utils/icq.rs index 574e220e..84413048 100644 --- a/local-interchaintest/src/utils/icq.rs +++ b/local-interchaintest/src/utils/icq.rs @@ -1,7 +1,15 @@ use std::{fs::File, io::Write, path::PathBuf}; -use localic_utils::{utils::test_context::TestContext, NEUTRON_CHAIN_NAME}; +use localic_std::{ + errors::LocalError, + modules::cosmwasm::{contract_execute, contract_query}, + types::TransactionResponse, +}; +use localic_utils::{utils::test_context::TestContext, DEFAULT_KEY, NEUTRON_CHAIN_NAME}; use log::info; +use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; +use serde_json::Value; +use valence_test_icq_lib::msg::{ExecuteMsg, QueryMsg}; pub fn generate_icq_relayer_config( test_ctx: &TestContext, @@ -147,3 +155,171 @@ pub fn start_icq_relayer() -> Result<(), Box> { Err(format!("Failed to start ICQ relayer: {error}").into()) } } + +pub fn try_parse_storage_value(storage_value: &StorageValue) -> Value { + let mut map = serde_json::Map::new(); + + // Add storage prefix + map.insert( + "storage_prefix".to_string(), + Value::String(storage_value.storage_prefix.clone()), + ); + + // Try UTF-8 string interpretation + if let Ok(key_str) = String::from_utf8(storage_value.key.to_vec()) { + map.insert("key_utf8".to_string(), Value::String(key_str)); + } + + if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { + map.insert("value_utf8".to_string(), Value::String(value_str)); + } + + // Try JSON interpretation + if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { + if let Ok(json_value) = serde_json::from_str(&value_str) { + map.insert("value_json".to_string(), json_value); + } + } + + if let Ok(value_str) = String::from_utf8(storage_value.key.to_vec()) { + if let Ok(json_value) = serde_json::from_str(&value_str) { + map.insert("key_json".to_string(), json_value); + } + } + + // Convert raw bytes to base64 + map.insert( + "key".to_string(), + Value::String(storage_value.key.to_string()), + ); + + Value::Object(map) +} + +pub fn register_kvq_balances_query( + test_ctx: &TestContext, + icq_lib: String, + domain: String, + path: String, + key: Vec, +) -> Result { + info!("registering ICQ KV query on domain {domain}..."); + + let register_kvq_msg = ExecuteMsg::RegisterKeyValueQuery { + connection_id: test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&domain) + .get(), + update_period: 5, + path, + key, + }; + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &serde_json::to_string(®ister_kvq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + "--amount 1000000untrn --gas 50000000", + ) +} + +pub fn register_icq_balances_query( + test_ctx: &TestContext, + icq_lib: String, + domain: String, + addr: String, + denoms: Vec, +) -> Result { + info!("registering ICQ balances query on domain {domain} for {addr}..."); + + let register_icq_msg = ExecuteMsg::RegisterBalancesQuery { + connection_id: test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&domain) + .get(), + update_period: 5, + addr, + denoms, + }; + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &serde_json::to_string(®ister_icq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + "--amount 1000000untrn --gas 50000000", + ) +} + +pub fn query_balance_query_id( + test_ctx: &TestContext, + icq_lib: String, + query_id: u64, +) -> Result { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::Balance { query_id }) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let balance_response: neutron_sdk::interchain_queries::v047::queries::BalanceResponse = + serde_json::from_value(query_response).unwrap(); + + info!("balance query response: {:?}", balance_response); + + Ok(balance_response) +} + +pub fn query_raw_result( + test_ctx: &TestContext, + icq_lib: String, + query_id: u64, +) -> Result { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::RawIcqResult { id: query_id }) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let icq_result: InterchainQueryResult = serde_json::from_value(query_response).unwrap(); + + info!("raw icq result: {:?}", icq_result); + + Ok(icq_result) +} + +pub fn query_catchall_logs( + test_ctx: &TestContext, + icq_lib: String, +) -> Result, LocalError> { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::Catchall {}) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let resp: Vec<(String, String)> = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} From c7351f30fcc885eea4b0b6e010ce485fddc43897 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 26 Nov 2024 20:47:50 +0100 Subject: [PATCH 45/92] decoding attempts --- Cargo.lock | 71 +++++++++++++- local-interchaintest/Cargo.toml | 2 + local-interchaintest/examples/icq_test.rs | 112 +++++++++++++--------- local-interchaintest/src/utils/icq.rs | 45 +++++++++ 4 files changed, 185 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cf1513d..383d7bc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -759,7 +759,7 @@ dependencies = [ "sha3", "subtle-encoding", "tokio", - "tonic", + "tonic 0.11.0", ] [[package]] @@ -782,6 +782,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "tendermint-proto 0.34.1", + "tonic 0.10.2", ] [[package]] @@ -793,7 +794,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "tendermint-proto 0.35.0", - "tonic", + "tonic 0.11.0", ] [[package]] @@ -2427,6 +2428,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2549,6 +2559,7 @@ version = "0.1.0" dependencies = [ "base64 0.13.1", "cosmos-grpc-client", + "cosmos-sdk-proto 0.20.0", "cosmwasm-std 1.5.8", "cosmwasm-std 2.1.4", "cw-utils 2.0.0", @@ -2562,6 +2573,7 @@ dependencies = [ "persistence-std", "polytone-note", "polytone-voice", + "prost 0.7.0", "rand 0.8.5", "serde_json", "sha2 0.10.8", @@ -3355,6 +3367,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" +dependencies = [ + "bytes", + "prost-derive 0.7.0", +] + [[package]] name = "prost" version = "0.11.9" @@ -3385,6 +3407,19 @@ dependencies = [ "prost-derive 0.13.3", ] +[[package]] +name = "prost-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" +dependencies = [ + "anyhow", + "itertools 0.9.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "prost-derive" version = "0.11.9" @@ -4813,6 +4848,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.7", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.12.6", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tonic" version = "0.11.0" @@ -5596,12 +5658,17 @@ dependencies = [ name = "valence-test-icq-lib" version = "0.1.0" dependencies = [ + "base64 0.21.7", "cosmos-sdk-proto 0.20.0", "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw2 2.0.0", "neutron-sdk", + "osmosis-std", + "prost 0.11.9", + "prost-types 0.11.9", + "protobuf 2.28.0", "schemars", "serde", "serde-json-wasm 1.0.1", diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index bb0f67ff..2ee7cf22 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -48,3 +48,5 @@ osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } base64 = "0.13.0" +prost = "0.7.0" +cosmos-sdk-proto = { version = "0.20.0" } diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index 1b5b5f7c..d4e49ac9 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -1,8 +1,11 @@ +use cosmos_grpc_client::cosmrs::bip32::secp256k1::pkcs8::der::Encode; use local_interchaintest::utils::{ icq::{ - generate_icq_relayer_config, query_catchall_logs, query_raw_result, - register_kvq_balances_query, start_icq_relayer, try_parse_storage_value, + generate_icq_relayer_config, query_balance_query_id, query_catchall_logs, query_raw_result, + register_icq_balances_query, register_kvq_balances_query, start_icq_relayer, + try_parse_storage_value, }, + osmosis::gamm::setup_gamm_pool, GAS_FLAGS, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, }; use localic_std::{ @@ -24,8 +27,8 @@ use valence_test_icq_lib::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use localic_utils::{ utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, - LOCAL_IC_API_URL, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, OSMOSIS_CHAIN_DENOM, - OSMOSIS_CHAIN_NAME, + LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, + OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_NAME, }; // KeyNextGlobalPoolId defines key to store the next Pool ID to be used. @@ -49,6 +52,15 @@ fn main() -> Result<(), Box> { .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) .build()?; + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + let current_dir = env::current_dir()?; // with test context set up, we can generate the .env file for the icq relayer @@ -99,30 +111,8 @@ fn main() -> Result<(), Box> { info!("icq test lib: {}", icq_test_lib.address); - // let icq_registration_response = register_icq_balances_query( - // &test_ctx, - // icq_test_lib.address.to_string(), - // OSMOSIS_CHAIN_NAME.to_string(), - // OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), - // vec![OSMOSIS_CHAIN_DENOM.to_string()], - // )?; - - // info!("icq registration response: {:?}", icq_registration_response); - - // for _ in 0..10 { - // let response_value = - // query_balance_query_id(&test_ctx, icq_test_lib.address.to_string(), 1)?; + let last_query_id = 20; - // info!("response value: {:?}", response_value); - - // if !response_value.balances.coins.is_empty() { - // break; - // } else { - // std::thread::sleep(Duration::from_secs(5)); - // } - // } - - std::thread::sleep(Duration::from_secs(3)); let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; let converted_addr_bytes = decode_and_convert(&addr).unwrap(); @@ -142,28 +132,64 @@ fn main() -> Result<(), Box> { kvq_registration_response ); - for _ in 0..2 { - let response_value = query_catchall_logs(&test_ctx, icq_test_lib.address.to_string())?; - info!("catchall logs: {:?}", response_value); + std::thread::sleep(Duration::from_secs(5)); - let raw_query_resp = query_raw_result(&test_ctx, icq_test_lib.address.to_string(), 1)?; - info!("raw query response: {:?}", raw_query_resp); + let raw_query_resp = query_raw_result( + &test_ctx, + icq_test_lib.address.to_string(), + last_query_id + 1, + )?; + info!("raw query response: {:?}", raw_query_resp); + + for kv_result in raw_query_resp.kv_results { + let parse_attempt = try_parse_storage_value(&kv_result); - for kv_result in raw_query_resp.kv_results { - // let key = kv_result.key; - // let value = kv_result.value; + info!("\nPARSE ATTEMPT: {:?}", parse_attempt); + } - let parse_attempt = try_parse_storage_value(&kv_result); + std::thread::sleep(Duration::from_secs(5)); - info!("\nPARSE ATTEMPT: {:?}", parse_attempt); - } + info!("attempting GAMM total liquidity query"); + + let mut total_liquidity_key = vec![PREFIX_POOLS_KEY]; + total_liquidity_key.extend_from_slice(&pool_id.to_be_bytes()); + + info!("base64 liquidity key: {:?}", total_liquidity_key); + + let kvq_registration_response = register_kvq_balances_query( + &test_ctx, + icq_test_lib.address.to_string(), + OSMOSIS_CHAIN_NAME.to_string(), + GAMM_STORE_KEY.to_string(), + total_liquidity_key, + )?; - if !response_value.is_empty() { - break; - } else { - std::thread::sleep(Duration::from_secs(5)); + info!( + "kv query registration response: {:?}", + kvq_registration_response + ); + + std::thread::sleep(Duration::from_secs(5)); + + match query_raw_result( + &test_ctx, + icq_test_lib.address.to_string(), + last_query_id + 2, + ) { + Ok(val) => { + info!("\nquery raw response: {:?}", val); + for kv_result in val.kv_results { + let parse_attempt = try_parse_storage_value(&kv_result); + + info!("\nPARSE ATTEMPT: {:?}", parse_attempt); + // osmosis_std::types::osmosis::concentratedliquidity::v1beta1::Pool + // osmosis_std::types::osmosis::gamm::v1beta1::Pool + } } - } + Err(e) => { + info!("error querying raw tx: {:?}", e); + } + }; Ok(()) } diff --git a/local-interchaintest/src/utils/icq.rs b/local-interchaintest/src/utils/icq.rs index 84413048..f7926fb4 100644 --- a/local-interchaintest/src/utils/icq.rs +++ b/local-interchaintest/src/utils/icq.rs @@ -1,5 +1,7 @@ use std::{fs::File, io::Write, path::PathBuf}; +use cosmos_sdk_proto::prost::Message; +use cosmwasm_std_old::from_json; use localic_std::{ errors::LocalError, modules::cosmwasm::{contract_execute, contract_query}, @@ -8,6 +10,7 @@ use localic_std::{ use localic_utils::{utils::test_context::TestContext, DEFAULT_KEY, NEUTRON_CHAIN_NAME}; use log::info; use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; +use osmosis_std::shim::Any; use serde_json::Value; use valence_test_icq_lib::msg::{ExecuteMsg, QueryMsg}; @@ -159,6 +162,48 @@ pub fn start_icq_relayer() -> Result<(), Box> { pub fn try_parse_storage_value(storage_value: &StorageValue) -> Value { let mut map = serde_json::Map::new(); + let storage_value_string = storage_value.value.to_string(); + let storage_value_b64 = storage_value.value.to_base64(); + // from_json(&serialized.as_slice()).unwrap(); + + let try_get_pool: cosmwasm_std_old::StdResult< + osmosis_std::types::osmosis::gamm::v1beta1::Pool, + > = from_json(storage_value.value.clone()); + + let res: Option = + storage_value.value.clone().try_into().ok(); + + // let opt_any: Option = storage_value.value.clone().try_into().ok(); + + match res { + Some(val) => { + info!("decoded value: {:?}", val); + } + None => { + info!("error decoding value: {:?}", "nothing"); + } + }; + // let slice_val = storage_value.value.as_(); + // let prost_bytes = prost::bytes::Bytes::from(storage_value.value.try_into().unwrap()); + // let prost_msg = prost::Message::decode(prost_bytes).unwrap(); + // let jsonval_decoded: Value = from_base64(storage_value_b64).unwrap(); + // Value::from_str(s) + // let jsonval = Value::from(storage_value.value); + // let pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = + // base64::de(storage_value.value.as_slice()).unwrap(); + // + map.insert( + "storage_value_string".to_string(), + Value::String(storage_value_string), + ); + map.insert( + "storage_value_b64".to_string(), + Value::String(storage_value_b64), + ); + + // let pool = + + // match from_json(&storage_value.) // Add storage prefix map.insert( "storage_prefix".to_string(), From c4a560210e69042e33956c24c5dae4553267d30e Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 27 Nov 2024 15:40:09 +0100 Subject: [PATCH 46/92] storing json in store --- Cargo.lock | 206 ++++++++++++------ contracts/testing/test-icq-lib/Cargo.toml | 12 +- .../testing/test-icq-lib/src/contract.rs | 5 +- contracts/testing/test-icq-lib/src/icq.rs | 91 +++++++- local-interchaintest/examples/icq_test.rs | 94 ++++---- 5 files changed, 283 insertions(+), 125 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 383d7bc0..becfae07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,7 +167,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -180,7 +180,7 @@ dependencies = [ "num-bigint", "num-traits", "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -216,7 +216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -286,7 +286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -297,7 +297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -436,7 +436,7 @@ dependencies = [ "log", "peeking_take_while", "proc-macro2", - "quote", + "quote 1.0.37", "regex", "rustc-hash", "shlex", @@ -456,7 +456,7 @@ dependencies = [ "log", "prettyplease", "proc-macro2", - "quote", + "quote 1.0.37", "regex", "rustc-hash", "shlex", @@ -906,7 +906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -943,7 +943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2411b389e56e6484f81ba955b758d02522d620c98fc960c4bd2251d48b7aa19f" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -954,7 +954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ef1b5835a65fcca3ab8b9a02b4f4dacc78e233a5c2f20b270efb9db0666d12" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1101,7 +1101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1203,7 +1203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e69178d27793063dd13812777709cf7d7860ba35a598094d4bd89e1b30c9341" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -1360,7 +1360,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote", + "quote 1.0.37", "strsim 0.11.1", "syn 2.0.89", ] @@ -1372,7 +1372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1416,7 +1416,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -1437,7 +1437,7 @@ checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1467,9 +1467,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", - "unicode-xid", + "unicode-xid 0.2.6", ] [[package]] @@ -1516,7 +1516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1643,7 +1643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -1699,6 +1699,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +dependencies = [ + "backtrace", +] + [[package]] name = "ethbloom" version = "0.6.4" @@ -1887,7 +1896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -1953,7 +1962,7 @@ checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" dependencies = [ "proc-macro-error2", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -2325,7 +2334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -2485,9 +2494,22 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" dependencies = [ - "pest", - "pest_derive", + "pest 2.7.14", + "pest_derive 2.7.14", + "serde", +] + +[[package]] +name = "jsonpath" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8061db09019f1879ba586685694fe18279f597b1b3a9dd308f35e596be6cdf7d" +dependencies = [ + "error-chain", + "pest 1.0.6", + "pest_derive 1.0.8", "serde", + "serde_json", ] [[package]] @@ -2839,7 +2861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -2850,7 +2872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -2937,7 +2959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3000,7 +3022,7 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "prost-types 0.11.9", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -3109,7 +3131,7 @@ checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" dependencies = [ "peg-runtime", "proc-macro2", - "quote", + "quote 1.0.37", ] [[package]] @@ -3150,10 +3172,16 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "prost-types 0.12.6", - "quote", + "quote 1.0.37", "syn 1.0.109", ] +[[package]] +name = "pest" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" + [[package]] name = "pest" version = "2.7.14" @@ -3165,13 +3193,24 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pest_derive" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4" +dependencies = [ + "pest 1.0.6", + "quote 0.3.15", + "syn 0.11.11", +] + [[package]] name = "pest_derive" version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ - "pest", + "pest 2.7.14", "pest_generator", ] @@ -3181,10 +3220,10 @@ version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ - "pest", + "pest 2.7.14", "pest_meta", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3195,7 +3234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", - "pest", + "pest 2.7.14", "sha2 0.10.8", ] @@ -3215,7 +3254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3343,7 +3382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", ] [[package]] @@ -3354,7 +3393,7 @@ checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ "proc-macro-error-attr2", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3416,7 +3455,7 @@ dependencies = [ "anyhow", "itertools 0.9.0", "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -3429,7 +3468,7 @@ dependencies = [ "anyhow", "itertools 0.10.5", "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -3442,7 +3481,7 @@ dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3455,7 +3494,7 @@ dependencies = [ "anyhow", "itertools 0.13.0", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -3534,6 +3573,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + [[package]] name = "quote" version = "1.0.37" @@ -3907,7 +3952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "serde_derive_internals", "syn 2.0.89", ] @@ -4023,7 +4068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4034,7 +4079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4067,7 +4112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4267,7 +4312,7 @@ checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", "proc-macro2", - "quote", + "quote 1.0.37", "rustversion", "syn 2.0.89", ] @@ -4280,7 +4325,7 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.37", "rustversion", "syn 2.0.89", ] @@ -4306,6 +4351,17 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] + [[package]] name = "syn" version = "1.0.109" @@ -4313,7 +4369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "unicode-ident", ] @@ -4324,7 +4380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "unicode-ident", ] @@ -4334,6 +4390,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -4341,7 +4406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4627,7 +4692,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4638,7 +4703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4766,7 +4831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -4952,7 +5017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -5054,6 +5119,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -5327,7 +5398,7 @@ dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "proc-macro2", - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -5658,17 +5729,16 @@ dependencies = [ name = "valence-test-icq-lib" version = "0.1.0" dependencies = [ - "base64 0.21.7", "cosmos-sdk-proto 0.20.0", "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw2 2.0.0", + "jsonpath", "neutron-sdk", "osmosis-std", - "prost 0.11.9", - "prost-types 0.11.9", - "protobuf 2.28.0", + "prost 0.13.3", + "prost-types 0.13.3", "schemars", "serde", "serde-json-wasm 1.0.1", @@ -5752,7 +5822,7 @@ dependencies = [ "log", "once_cell", "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", "wasm-bindgen-shared", ] @@ -5775,7 +5845,7 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ - "quote", + "quote 1.0.37", "wasm-bindgen-macro-support", ] @@ -5786,7 +5856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -6066,7 +6136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", "synstructure", ] @@ -6088,7 +6158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -6108,7 +6178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", "synstructure", ] @@ -6129,7 +6199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] @@ -6151,6 +6221,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.37", "syn 2.0.89", ] diff --git a/contracts/testing/test-icq-lib/Cargo.toml b/contracts/testing/test-icq-lib/Cargo.toml index c248bd45..cbbfa77d 100644 --- a/contracts/testing/test-icq-lib/Cargo.toml +++ b/contracts/testing/test-icq-lib/Cargo.toml @@ -27,6 +27,12 @@ neutron-sdk = { workspace = true } serde-json-wasm = "1.0.0" cw2 = { workspace = true } cosmos-sdk-proto = { workspace = true } -schemars = { workspace = true } -serde_json = { workspace = true } -serde = { workspace = true } +schemars = { workspace = true } +serde_json = { workspace = true } +serde = { workspace = true } +osmosis-std = { workspace = true } +prost = {version = "0.13.3", default-features = false, features = [ + "prost-derive", +]} +prost-types = {version = "0.13.3", default-features = false} +jsonpath = "0.1.1" diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index 8893702f..d424c018 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -6,22 +6,19 @@ use cosmos_sdk_proto::prost::Message; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, + to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, }; use cw2::set_contract_version; use cw_storage_plus::KeyDeserialize; use neutron_sdk::interchain_queries::queries::get_raw_interchain_query_result; -use neutron_sdk::interchain_txs::helpers::decode_message_response; use neutron_sdk::sudo::msg::RequestPacket; -use neutron_sdk::NeutronError; use neutron_sdk::{ bindings::{msg::NeutronMsg, query::NeutronQuery}, interchain_queries::v047::queries::{query_balance, BalanceResponse}, sudo::msg::SudoMsg, NeutronResult, }; -use serde_json::value::Serializer; pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index 5b582890..6a702291 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -5,17 +5,18 @@ use cosmos_sdk_proto::{ }, prost::Message, }; -use cosmwasm_std::{Binary, DepsMut, Env, Response}; +use cosmwasm_std::{to_json_string, Binary, DepsMut, Env, Response}; use neutron_sdk::{ bindings::{ msg::NeutronMsg, query::NeutronQuery, - types::{Height, KVKey}, + types::{Height, KVKey, StorageValue}, }, interchain_queries::{ get_registered_query, helpers::decode_and_convert, - types::QueryPayload, + query_kv_result, + types::{KVReconstruct, QueryPayload}, v045::{ new_register_balances_query_msg, new_register_distribution_fee_pool_query_msg, new_register_transfers_query_msg, @@ -29,6 +30,8 @@ use neutron_sdk::{ NeutronResult, }; +use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool as GammPool}; + use cosmwasm_std::{StdError, StdResult}; use neutron_sdk::bindings::query::QueryRegisteredQueryResponse; @@ -37,9 +40,12 @@ use neutron_sdk::interchain_queries::v047::types::{COSMOS_SDK_TRANSFER_MSG_URL, use neutron_sdk::interchain_queries::types::{ TransactionFilterItem, TransactionFilterOp, TransactionFilterValue, }; +use prost::Message as _; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; use serde_json_wasm; -use crate::state::{Transfer, RECIPIENT_TXS, TRANSFERS}; +use crate::state::{Transfer, CATCHALL, RECIPIENT_TXS, TRANSFERS}; const MAX_ALLOWED_MESSAGES: usize = 20; @@ -167,9 +173,50 @@ pub fn sudo_kv_query_result( ) .as_str(), ); + + let reconstruct_result: NeutronResult = query_kv_result(deps.as_ref(), query_id); + + match reconstruct_result { + Ok(val) => { + let json_str_pool = to_json_string(&val.0)?; + + CATCHALL.save( + deps.storage, + "json_deserialize_pool".to_string(), + &json_str_pool, + )?; + } + Err(e) => { + CATCHALL.save( + deps.storage, + "json_deserialize_pool_error".to_string(), + &e.to_string(), + )?; + } + }; + Ok(Response::default()) } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct PoolWrapper(GammPool); + +impl KVReconstruct for PoolWrapper { + fn reconstruct(kvs: &[StorageValue]) -> NeutronResult { + if let Some(kv) = kvs.first() { + // need to go to Any first and then to type: + let any_msg: Any = Any::decode(kv.value.as_slice()).unwrap(); + + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = + any_msg.try_into().unwrap(); + + return Ok(PoolWrapper(osmo_pool)); + } + + Err(StdError::generic_err("failed to reconstruct pool".to_string()).into()) + } +} + pub fn register_transfers_query( connection_id: String, recipient: String, @@ -201,3 +248,39 @@ pub fn register_kv_query( Ok(Response::new().add_message(msg)) } + +#[cfg(test)] +mod test { + use cosmwasm_std::{to_json_string, Binary}; + use neutron_sdk::bindings::types::StorageValue; + use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; + use prost::Message; + use serde_json::Value; + + #[test] + fn try_decode_osmo_pool_from_binary() { + let key_utf8 = "\u{2}\0\0\0\0\0\0\0\u{1}"; + let binary_key = Binary::from(key_utf8.as_bytes()); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "gamm".to_string(), + key: binary_key, + value: binary_value, + }; + + // need to go to Any first and then to type: + let any_msg: Any = Any::decode(storage_value.value.as_slice()).unwrap(); + assert_eq!(any_msg.type_url, "/osmosis.gamm.v1beta1.Pool"); + + let osmo_pool: Pool = any_msg.try_into().unwrap(); + + println!("osmo pool : {:?}", osmo_pool); + + let json_str: String = to_json_string(&osmo_pool).unwrap(); + let json_value: Value = serde_json::from_str(&json_str).unwrap(); + println!("json value: {:?}", json_value); + } +} diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index d4e49ac9..4d56e843 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -111,43 +111,43 @@ fn main() -> Result<(), Box> { info!("icq test lib: {}", icq_test_lib.address); - let last_query_id = 20; + let last_query_id = 4; - let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; + // let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; - let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + // let converted_addr_bytes = decode_and_convert(&addr).unwrap(); - let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); + // let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); - let kvq_registration_response = register_kvq_balances_query( - &test_ctx, - icq_test_lib.address.to_string(), - OSMOSIS_CHAIN_NAME.to_string(), - BANK_STORE_KEY.to_string(), - balance_key, - )?; + // let kvq_registration_response = register_kvq_balances_query( + // &test_ctx, + // icq_test_lib.address.to_string(), + // OSMOSIS_CHAIN_NAME.to_string(), + // BANK_STORE_KEY.to_string(), + // balance_key, + // )?; - info!( - "kv query registration response: {:?}", - kvq_registration_response - ); + // info!( + // "kv query registration response: {:?}", + // kvq_registration_response + // ); - std::thread::sleep(Duration::from_secs(5)); + // std::thread::sleep(Duration::from_secs(5)); - let raw_query_resp = query_raw_result( - &test_ctx, - icq_test_lib.address.to_string(), - last_query_id + 1, - )?; - info!("raw query response: {:?}", raw_query_resp); + // let raw_query_resp = query_raw_result( + // &test_ctx, + // icq_test_lib.address.to_string(), + // last_query_id + 1, + // )?; + // info!("raw query response: {:?}", raw_query_resp); - for kv_result in raw_query_resp.kv_results { - let parse_attempt = try_parse_storage_value(&kv_result); + // for kv_result in raw_query_resp.kv_results { + // let parse_attempt = try_parse_storage_value(&kv_result); - info!("\nPARSE ATTEMPT: {:?}", parse_attempt); - } + // info!("\nPARSE ATTEMPT: {:?}", parse_attempt); + // } - std::thread::sleep(Duration::from_secs(5)); + // std::thread::sleep(Duration::from_secs(5)); info!("attempting GAMM total liquidity query"); @@ -171,25 +171,27 @@ fn main() -> Result<(), Box> { std::thread::sleep(Duration::from_secs(5)); - match query_raw_result( - &test_ctx, - icq_test_lib.address.to_string(), - last_query_id + 2, - ) { - Ok(val) => { - info!("\nquery raw response: {:?}", val); - for kv_result in val.kv_results { - let parse_attempt = try_parse_storage_value(&kv_result); - - info!("\nPARSE ATTEMPT: {:?}", parse_attempt); - // osmosis_std::types::osmosis::concentratedliquidity::v1beta1::Pool - // osmosis_std::types::osmosis::gamm::v1beta1::Pool - } - } - Err(e) => { - info!("error querying raw tx: {:?}", e); - } - }; + let catchall_logs = query_catchall_logs(&test_ctx, icq_test_lib.address.to_string())?; + info!("catchall logs: {:?}", catchall_logs); + // match query_raw_result( + // &test_ctx, + // icq_test_lib.address.to_string(), + // last_query_id + 1, + // ) { + // Ok(val) => { + // info!("\nquery raw response: {:?}", val); + // for kv_result in val.kv_results { + // let parse_attempt = try_parse_storage_value(&kv_result); + + // info!("\nPARSE ATTEMPT: {:?}", parse_attempt); + // // osmosis_std::types::osmosis::concentratedliquidity::v1beta1::Pool + // // osmosis_std::types::osmosis::gamm::v1beta1::Pool + // } + // } + // Err(e) => { + // info!("error querying raw tx: {:?}", e); + // } + // }; Ok(()) } From 51aba701625024ce2b242bafe4676e70848d32fe Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 27 Nov 2024 15:57:40 +0100 Subject: [PATCH 47/92] cleanup --- .../testing/test-icq-lib/src/contract.rs | 5 +- contracts/testing/test-icq-lib/src/icq.rs | 40 ++----- contracts/testing/test-icq-lib/src/msg.rs | 1 - local-interchaintest/examples/icq_test.rs | 86 ++------------- local-interchaintest/src/utils/icq.rs | 101 +----------------- 5 files changed, 21 insertions(+), 212 deletions(-) diff --git a/contracts/testing/test-icq-lib/src/contract.rs b/contracts/testing/test-icq-lib/src/contract.rs index d424c018..585cde54 100644 --- a/contracts/testing/test-icq-lib/src/contract.rs +++ b/contracts/testing/test-icq-lib/src/contract.rs @@ -173,9 +173,8 @@ fn sudo_open_ack( counterparty_version: String, ) -> StdResult> { // parse the response - let parsed_version: OpenAckVersion = - serde_json_wasm::from_str(counterparty_version.as_str()) - .map_err(|_| StdError::generic_err("Can't parse counterparty_version"))?; + let _parsed_version: OpenAckVersion = serde_json_wasm::from_str(counterparty_version.as_str()) + .map_err(|_| StdError::generic_err("Can't parse counterparty_version"))?; CATCHALL.save(deps.storage, "sudo_open_ack".to_string(), &port_id)?; diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index 6a702291..f3c3776a 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -14,18 +14,9 @@ use neutron_sdk::{ }, interchain_queries::{ get_registered_query, - helpers::decode_and_convert, - query_kv_result, + queries::get_raw_interchain_query_result, types::{KVReconstruct, QueryPayload}, - v045::{ - new_register_balances_query_msg, new_register_distribution_fee_pool_query_msg, - new_register_transfers_query_msg, - }, - v047::{ - helpers::create_account_denom_balance_key, - register_queries::new_register_delegator_delegations_query_msg, - types::{BANK_STORE_KEY, DISTRIBUTION_STORE_KEY, SUPPLY_PREFIX}, - }, + v045::{new_register_balances_query_msg, new_register_transfers_query_msg}, }, NeutronResult, }; @@ -174,26 +165,15 @@ pub fn sudo_kv_query_result( .as_str(), ); - let reconstruct_result: NeutronResult = query_kv_result(deps.as_ref(), query_id); + let registered_query_result = get_raw_interchain_query_result(deps.as_ref(), query_id) + .map_err(|_| StdError::generic_err("failed to get the raw icq result"))?; - match reconstruct_result { - Ok(val) => { - let json_str_pool = to_json_string(&val.0)?; - - CATCHALL.save( - deps.storage, - "json_deserialize_pool".to_string(), - &json_str_pool, - )?; - } - Err(e) => { - CATCHALL.save( - deps.storage, - "json_deserialize_pool_error".to_string(), - &e.to_string(), - )?; - } - }; + let query_result_str = to_json_string(®istered_query_result.result)?; + CATCHALL.save( + deps.storage, + registered_query_result.result.height.to_string(), + &query_result_str, + )?; Ok(Response::default()) } diff --git a/contracts/testing/test-icq-lib/src/msg.rs b/contracts/testing/test-icq-lib/src/msg.rs index 92fb3f23..f848ce90 100644 --- a/contracts/testing/test-icq-lib/src/msg.rs +++ b/contracts/testing/test-icq-lib/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use neutron_sdk::{ bindings::types::InterchainQueryResult, interchain_queries::v047::queries::BalanceResponse, - proto_types::neutron::interchainqueries::QueryResult, }; #[cw_serde] diff --git a/local-interchaintest/examples/icq_test.rs b/local-interchaintest/examples/icq_test.rs index 4d56e843..84a83a9f 100644 --- a/local-interchaintest/examples/icq_test.rs +++ b/local-interchaintest/examples/icq_test.rs @@ -1,34 +1,19 @@ -use cosmos_grpc_client::cosmrs::bip32::secp256k1::pkcs8::der::Encode; use local_interchaintest::utils::{ icq::{ - generate_icq_relayer_config, query_balance_query_id, query_catchall_logs, query_raw_result, - register_icq_balances_query, register_kvq_balances_query, start_icq_relayer, - try_parse_storage_value, + generate_icq_relayer_config, query_catchall_logs, register_kvq_balances_query, + start_icq_relayer, }, osmosis::gamm::setup_gamm_pool, - GAS_FLAGS, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, -}; -use localic_std::{ - errors::LocalError, - modules::cosmwasm::{contract_execute, contract_instantiate, contract_query}, - types::TransactionResponse, + LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, }; +use localic_std::modules::cosmwasm::contract_instantiate; use log::info; -use neutron_sdk::{ - bindings::types::{InterchainQueryResult, StorageValue}, - interchain_queries::{ - helpers::decode_and_convert, - v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, - }, -}; -use serde_json::Value; use std::{env, error::Error, time::Duration}; -use valence_test_icq_lib::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use valence_test_icq_lib::msg::InstantiateMsg; use localic_utils::{ - utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, - LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, - OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_NAME, + ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, + NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_NAME, }; // KeyNextGlobalPoolId defines key to store the next Pool ID to be used. @@ -111,44 +96,6 @@ fn main() -> Result<(), Box> { info!("icq test lib: {}", icq_test_lib.address); - let last_query_id = 4; - - // let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; - - // let converted_addr_bytes = decode_and_convert(&addr).unwrap(); - - // let balance_key = create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); - - // let kvq_registration_response = register_kvq_balances_query( - // &test_ctx, - // icq_test_lib.address.to_string(), - // OSMOSIS_CHAIN_NAME.to_string(), - // BANK_STORE_KEY.to_string(), - // balance_key, - // )?; - - // info!( - // "kv query registration response: {:?}", - // kvq_registration_response - // ); - - // std::thread::sleep(Duration::from_secs(5)); - - // let raw_query_resp = query_raw_result( - // &test_ctx, - // icq_test_lib.address.to_string(), - // last_query_id + 1, - // )?; - // info!("raw query response: {:?}", raw_query_resp); - - // for kv_result in raw_query_resp.kv_results { - // let parse_attempt = try_parse_storage_value(&kv_result); - - // info!("\nPARSE ATTEMPT: {:?}", parse_attempt); - // } - - // std::thread::sleep(Duration::from_secs(5)); - info!("attempting GAMM total liquidity query"); let mut total_liquidity_key = vec![PREFIX_POOLS_KEY]; @@ -173,25 +120,6 @@ fn main() -> Result<(), Box> { let catchall_logs = query_catchall_logs(&test_ctx, icq_test_lib.address.to_string())?; info!("catchall logs: {:?}", catchall_logs); - // match query_raw_result( - // &test_ctx, - // icq_test_lib.address.to_string(), - // last_query_id + 1, - // ) { - // Ok(val) => { - // info!("\nquery raw response: {:?}", val); - // for kv_result in val.kv_results { - // let parse_attempt = try_parse_storage_value(&kv_result); - - // info!("\nPARSE ATTEMPT: {:?}", parse_attempt); - // // osmosis_std::types::osmosis::concentratedliquidity::v1beta1::Pool - // // osmosis_std::types::osmosis::gamm::v1beta1::Pool - // } - // } - // Err(e) => { - // info!("error querying raw tx: {:?}", e); - // } - // }; Ok(()) } diff --git a/local-interchaintest/src/utils/icq.rs b/local-interchaintest/src/utils/icq.rs index f7926fb4..c0af427a 100644 --- a/local-interchaintest/src/utils/icq.rs +++ b/local-interchaintest/src/utils/icq.rs @@ -1,7 +1,5 @@ use std::{fs::File, io::Write, path::PathBuf}; -use cosmos_sdk_proto::prost::Message; -use cosmwasm_std_old::from_json; use localic_std::{ errors::LocalError, modules::cosmwasm::{contract_execute, contract_query}, @@ -9,9 +7,7 @@ use localic_std::{ }; use localic_utils::{utils::test_context::TestContext, DEFAULT_KEY, NEUTRON_CHAIN_NAME}; use log::info; -use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; -use osmosis_std::shim::Any; -use serde_json::Value; +use neutron_sdk::bindings::types::InterchainQueryResult; use valence_test_icq_lib::msg::{ExecuteMsg, QueryMsg}; pub fn generate_icq_relayer_config( @@ -83,18 +79,7 @@ RELAYER_IGNORE_ERRORS_REGEX=(execute wasm contract failed|failed to build tx que } pub fn start_icq_relayer() -> Result<(), Box> { - // match std::process::Command::new("docker") - // .arg("inspect") - // .arg("icq-relayer") - // .output() - // { - // Ok(r) => { - // info!("ICQ relayer already running: {:?}", r); - // return Ok(()); - // } - // Err(e) => info!("inspect icq relayer error: {:?}", e), - // }; - // First try to stop and remove any existing icq-relayer container + // try to stop and remove any existing icq-relayer container from host let _ = std::process::Command::new("docker") .arg("stop") .arg("icq-relayer") @@ -159,88 +144,6 @@ pub fn start_icq_relayer() -> Result<(), Box> { } } -pub fn try_parse_storage_value(storage_value: &StorageValue) -> Value { - let mut map = serde_json::Map::new(); - - let storage_value_string = storage_value.value.to_string(); - let storage_value_b64 = storage_value.value.to_base64(); - // from_json(&serialized.as_slice()).unwrap(); - - let try_get_pool: cosmwasm_std_old::StdResult< - osmosis_std::types::osmosis::gamm::v1beta1::Pool, - > = from_json(storage_value.value.clone()); - - let res: Option = - storage_value.value.clone().try_into().ok(); - - // let opt_any: Option = storage_value.value.clone().try_into().ok(); - - match res { - Some(val) => { - info!("decoded value: {:?}", val); - } - None => { - info!("error decoding value: {:?}", "nothing"); - } - }; - // let slice_val = storage_value.value.as_(); - // let prost_bytes = prost::bytes::Bytes::from(storage_value.value.try_into().unwrap()); - // let prost_msg = prost::Message::decode(prost_bytes).unwrap(); - // let jsonval_decoded: Value = from_base64(storage_value_b64).unwrap(); - // Value::from_str(s) - // let jsonval = Value::from(storage_value.value); - // let pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = - // base64::de(storage_value.value.as_slice()).unwrap(); - // - map.insert( - "storage_value_string".to_string(), - Value::String(storage_value_string), - ); - map.insert( - "storage_value_b64".to_string(), - Value::String(storage_value_b64), - ); - - // let pool = - - // match from_json(&storage_value.) - // Add storage prefix - map.insert( - "storage_prefix".to_string(), - Value::String(storage_value.storage_prefix.clone()), - ); - - // Try UTF-8 string interpretation - if let Ok(key_str) = String::from_utf8(storage_value.key.to_vec()) { - map.insert("key_utf8".to_string(), Value::String(key_str)); - } - - if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { - map.insert("value_utf8".to_string(), Value::String(value_str)); - } - - // Try JSON interpretation - if let Ok(value_str) = String::from_utf8(storage_value.value.to_vec()) { - if let Ok(json_value) = serde_json::from_str(&value_str) { - map.insert("value_json".to_string(), json_value); - } - } - - if let Ok(value_str) = String::from_utf8(storage_value.key.to_vec()) { - if let Ok(json_value) = serde_json::from_str(&value_str) { - map.insert("key_json".to_string(), json_value); - } - } - - // Convert raw bytes to base64 - map.insert( - "key".to_string(), - Value::String(storage_value.key.to_string()), - ); - - Value::Object(map) -} - pub fn register_kvq_balances_query( test_ctx: &TestContext, icq_lib: String, From aa25831639ed9870d114597fddf50cbaeae6a3a6 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 27 Nov 2024 16:00:04 +0100 Subject: [PATCH 48/92] cleanup cargos --- Cargo.lock | 271 ++++++---------------- contracts/testing/test-icq-lib/Cargo.toml | 14 +- local-interchaintest/Cargo.toml | 3 - 3 files changed, 68 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index becfae07..4713b9ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,7 +167,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -180,7 +180,7 @@ dependencies = [ "num-bigint", "num-traits", "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -216,7 +216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -286,7 +286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -297,7 +297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -384,12 +384,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -436,7 +430,7 @@ dependencies = [ "log", "peeking_take_while", "proc-macro2", - "quote 1.0.37", + "quote", "regex", "rustc-hash", "shlex", @@ -456,7 +450,7 @@ dependencies = [ "log", "prettyplease", "proc-macro2", - "quote 1.0.37", + "quote", "regex", "rustc-hash", "shlex", @@ -759,7 +753,7 @@ dependencies = [ "sha3", "subtle-encoding", "tokio", - "tonic 0.11.0", + "tonic", ] [[package]] @@ -782,7 +776,6 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "tendermint-proto 0.34.1", - "tonic 0.10.2", ] [[package]] @@ -794,7 +787,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "tendermint-proto 0.35.0", - "tonic 0.11.0", + "tonic", ] [[package]] @@ -906,7 +899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -943,7 +936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2411b389e56e6484f81ba955b758d02522d620c98fc960c4bd2251d48b7aa19f" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -954,7 +947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ef1b5835a65fcca3ab8b9a02b4f4dacc78e233a5c2f20b270efb9db0666d12" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1101,7 +1094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1203,7 +1196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e69178d27793063dd13812777709cf7d7860ba35a598094d4bd89e1b30c9341" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -1360,7 +1353,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.37", + "quote", "strsim 0.11.1", "syn 2.0.89", ] @@ -1372,7 +1365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1416,7 +1409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -1437,7 +1430,7 @@ checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1467,9 +1460,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", - "unicode-xid 0.2.6", + "unicode-xid", ] [[package]] @@ -1516,7 +1509,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1643,7 +1636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -1699,15 +1692,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-chain" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -dependencies = [ - "backtrace", -] - [[package]] name = "ethbloom" version = "0.6.4" @@ -1896,7 +1880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -1962,7 +1946,7 @@ checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" dependencies = [ "proc-macro-error2", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -2334,7 +2318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -2437,15 +2421,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.10.5" @@ -2494,22 +2469,9 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" dependencies = [ - "pest 2.7.14", - "pest_derive 2.7.14", - "serde", -] - -[[package]] -name = "jsonpath" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8061db09019f1879ba586685694fe18279f597b1b3a9dd308f35e596be6cdf7d" -dependencies = [ - "error-chain", - "pest 1.0.6", - "pest_derive 1.0.8", + "pest", + "pest_derive", "serde", - "serde_json", ] [[package]] @@ -2579,9 +2541,7 @@ checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" name = "local-interchaintest" version = "0.1.0" dependencies = [ - "base64 0.13.1", "cosmos-grpc-client", - "cosmos-sdk-proto 0.20.0", "cosmwasm-std 1.5.8", "cosmwasm-std 2.1.4", "cw-utils 2.0.0", @@ -2595,7 +2555,6 @@ dependencies = [ "persistence-std", "polytone-note", "polytone-voice", - "prost 0.7.0", "rand 0.8.5", "serde_json", "sha2 0.10.8", @@ -2861,7 +2820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -2872,7 +2831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -2959,7 +2918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3022,7 +2981,7 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "prost-types 0.11.9", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -3131,7 +3090,7 @@ checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" dependencies = [ "peg-runtime", "proc-macro2", - "quote 1.0.37", + "quote", ] [[package]] @@ -3172,16 +3131,10 @@ dependencies = [ "itertools 0.10.5", "proc-macro2", "prost-types 0.12.6", - "quote 1.0.37", + "quote", "syn 1.0.109", ] -[[package]] -name = "pest" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" - [[package]] name = "pest" version = "2.7.14" @@ -3193,24 +3146,13 @@ dependencies = [ "ucd-trie", ] -[[package]] -name = "pest_derive" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4" -dependencies = [ - "pest 1.0.6", - "quote 0.3.15", - "syn 0.11.11", -] - [[package]] name = "pest_derive" version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ - "pest 2.7.14", + "pest", "pest_generator", ] @@ -3220,10 +3162,10 @@ version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ - "pest 2.7.14", + "pest", "pest_meta", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3234,7 +3176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", - "pest 2.7.14", + "pest", "sha2 0.10.8", ] @@ -3254,7 +3196,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3382,7 +3324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", ] [[package]] @@ -3393,7 +3335,7 @@ checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ "proc-macro-error-attr2", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3406,16 +3348,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6984d2f1a23009bd270b8bb56d0926810a3d483f59c987d77969e9d8e840b2" -dependencies = [ - "bytes", - "prost-derive 0.7.0", -] - [[package]] name = "prost" version = "0.11.9" @@ -3446,19 +3378,6 @@ dependencies = [ "prost-derive 0.13.3", ] -[[package]] -name = "prost-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4" -dependencies = [ - "anyhow", - "itertools 0.9.0", - "proc-macro2", - "quote 1.0.37", - "syn 1.0.109", -] - [[package]] name = "prost-derive" version = "0.11.9" @@ -3468,7 +3387,7 @@ dependencies = [ "anyhow", "itertools 0.10.5", "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -3481,7 +3400,7 @@ dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3494,7 +3413,7 @@ dependencies = [ "anyhow", "itertools 0.13.0", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -3573,12 +3492,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" - [[package]] name = "quote" version = "1.0.37" @@ -3952,7 +3865,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "serde_derive_internals", "syn 2.0.89", ] @@ -4068,7 +3981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4079,7 +3992,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4112,7 +4025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4312,7 +4225,7 @@ checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", "proc-macro2", - "quote 1.0.37", + "quote", "rustversion", "syn 2.0.89", ] @@ -4325,7 +4238,7 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote 1.0.37", + "quote", "rustversion", "syn 2.0.89", ] @@ -4351,17 +4264,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -dependencies = [ - "quote 0.3.15", - "synom", - "unicode-xid 0.0.4", -] - [[package]] name = "syn" version = "1.0.109" @@ -4369,7 +4271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "unicode-ident", ] @@ -4380,7 +4282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "unicode-ident", ] @@ -4390,15 +4292,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -dependencies = [ - "unicode-xid 0.0.4", -] - [[package]] name = "synstructure" version = "0.13.1" @@ -4406,7 +4299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4692,7 +4585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4703,7 +4596,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4831,7 +4724,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -4913,33 +4806,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tonic" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" -dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64 0.21.7", - "bytes", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.12.6", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tonic" version = "0.11.0" @@ -5017,7 +4883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -5119,12 +4985,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" - [[package]] name = "unicode-xid" version = "0.2.6" @@ -5398,7 +5258,7 @@ dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "proc-macro2", - "quote 1.0.37", + "quote", "syn 1.0.109", ] @@ -5734,7 +5594,6 @@ dependencies = [ "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw2 2.0.0", - "jsonpath", "neutron-sdk", "osmosis-std", "prost 0.13.3", @@ -5822,7 +5681,7 @@ dependencies = [ "log", "once_cell", "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", "wasm-bindgen-shared", ] @@ -5845,7 +5704,7 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ - "quote 1.0.37", + "quote", "wasm-bindgen-macro-support", ] @@ -5856,7 +5715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -6136,7 +5995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", "synstructure", ] @@ -6158,7 +6017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -6178,7 +6037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", "synstructure", ] @@ -6199,7 +6058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] @@ -6221,6 +6080,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", - "quote 1.0.37", + "quote", "syn 2.0.89", ] diff --git a/contracts/testing/test-icq-lib/Cargo.toml b/contracts/testing/test-icq-lib/Cargo.toml index cbbfa77d..ed396628 100644 --- a/contracts/testing/test-icq-lib/Cargo.toml +++ b/contracts/testing/test-icq-lib/Cargo.toml @@ -13,12 +13,7 @@ crate-type = ["cdylib", "rlib"] library = [] [dependencies] -# cosmwasm-std = { workspace = true } -cosmwasm-std = { version = "2.1.3", features = [ - "cosmwasm_1_1", - "cosmwasm_1_2", - "cosmwasm_1_4", -] } +cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } cw-storage-plus = { workspace = true } thiserror = { workspace = true } @@ -31,8 +26,5 @@ schemars = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } osmosis-std = { workspace = true } -prost = {version = "0.13.3", default-features = false, features = [ - "prost-derive", -]} -prost-types = {version = "0.13.3", default-features = false} -jsonpath = "0.1.1" +prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } +prost-types = { version = "0.13.3", default-features = false } diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 2ee7cf22..acbdd485 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -47,6 +47,3 @@ tokio = { workspace = true } osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } -base64 = "0.13.0" -prost = "0.7.0" -cosmos-sdk-proto = { version = "0.20.0" } From 61139eeef78e1f8b8a386188266e82c0a8de3a79 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 27 Nov 2024 16:28:33 +0100 Subject: [PATCH 49/92] init icq-querier library --- Cargo.lock | 17 +++++ Cargo.toml | 1 + .../libraries/icq-querier/.cargo/config.toml | 3 + contracts/libraries/icq-querier/Cargo.toml | 30 ++++++++ contracts/libraries/icq-querier/README.md | 1 + .../libraries/icq-querier/src/contract.rs | 73 +++++++++++++++++++ contracts/libraries/icq-querier/src/lib.rs | 4 + contracts/libraries/icq-querier/src/msg.rs | 65 +++++++++++++++++ .../libraries/icq-querier/src/testing/mod.rs | 2 + .../icq-querier/src/testing/tests.rs | 1 + 10 files changed, 197 insertions(+) create mode 100644 contracts/libraries/icq-querier/.cargo/config.toml create mode 100644 contracts/libraries/icq-querier/Cargo.toml create mode 100644 contracts/libraries/icq-querier/README.md create mode 100644 contracts/libraries/icq-querier/src/contract.rs create mode 100644 contracts/libraries/icq-querier/src/lib.rs create mode 100644 contracts/libraries/icq-querier/src/msg.rs create mode 100644 contracts/libraries/icq-querier/src/testing/mod.rs create mode 100644 contracts/libraries/icq-querier/src/testing/tests.rs diff --git a/Cargo.lock b/Cargo.lock index b037fca8..12c3ce10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5212,6 +5212,23 @@ dependencies = [ "serde", ] +[[package]] +name = "valence-icq-querier" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-ownable", + "cw20 2.0.0", + "osmosis-std", + "osmosis-test-tube", + "valence-account-utils", + "valence-library-base", + "valence-library-utils", + "valence-macros", + "valence-osmosis-utils", +] + [[package]] name = "valence-library-base" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7b29ad6f..8d57bcc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,7 @@ valence-osmosis-gamm-lper = { path = "contracts/libraries/osmosis-gam valence-osmosis-gamm-withdrawer = { path = "contracts/libraries/osmosis-gamm-withdrawer", features = ["library"] } valence-osmosis-cl-lper = { path = "contracts/libraries/osmosis-cl-lper", features = ["library"] } valence-osmosis-cl-withdrawer = { path = "contracts/libraries/osmosis-cl-withdrawer", features = ["library"] } +valence-icq-querier = { path = "contracts/libraries/icq-querier", features = ["library"] } # our packages valence-account-utils = { path = "packages/account-utils" } diff --git a/contracts/libraries/icq-querier/.cargo/config.toml b/contracts/libraries/icq-querier/.cargo/config.toml new file mode 100644 index 00000000..5f6aa466 --- /dev/null +++ b/contracts/libraries/icq-querier/.cargo/config.toml @@ -0,0 +1,3 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +schema = "run --bin schema" diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml new file mode 100644 index 00000000..cb5b2912 --- /dev/null +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "valence-icq-querier" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +version = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-ownable = { workspace = true } +valence-macros = { workspace = true } +valence-library-utils = { workspace = true } +valence-library-base = { workspace = true } +osmosis-std = { workspace = true } +valence-account-utils = { workspace = true } +valence-osmosis-utils = { workspace = true } + +[dev-dependencies] +cw20 = { workspace = true } +osmosis-test-tube = { workspace = true } +valence-osmosis-utils = { workspace = true, features = ["testing"] } diff --git a/contracts/libraries/icq-querier/README.md b/contracts/libraries/icq-querier/README.md new file mode 100644 index 00000000..d2cfd45a --- /dev/null +++ b/contracts/libraries/icq-querier/README.md @@ -0,0 +1 @@ +# ICQ-querier library diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs new file mode 100644 index 00000000..3bbc31cb --- /dev/null +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -0,0 +1,73 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use valence_library_utils::{ + error::LibraryError, + msg::{ExecuteMsg, InstantiateMsg}, +}; + +use crate::msg::{Config, FunctionMsgs, LibraryConfig, LibraryConfigUpdate, QueryMsg}; + +// version info for migration info +const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + valence_library_base::instantiate(deps, CONTRACT_NAME, CONTRACT_VERSION, msg) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + valence_library_base::execute(deps, env, info, msg, process_function, update_config) +} + +pub fn update_config( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + new_config: LibraryConfigUpdate, +) -> Result<(), LibraryError> { + new_config.update_config(deps) +} + +pub fn process_function( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: FunctionMsgs, + cfg: Config, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Ownership {} => { + to_json_binary(&valence_library_base::get_ownership(deps.storage)?) + } + QueryMsg::GetProcessor {} => { + to_json_binary(&valence_library_base::get_processor(deps.storage)?) + } + QueryMsg::GetLibraryConfig {} => { + let config: Config = valence_library_base::load_config(deps.storage)?; + to_json_binary(&config) + } + QueryMsg::GetRawLibraryConfig {} => { + let raw_config: LibraryConfig = + valence_library_utils::raw_config::query_raw_library_config(deps.storage)?; + to_json_binary(&raw_config) + } + } +} diff --git a/contracts/libraries/icq-querier/src/lib.rs b/contracts/libraries/icq-querier/src/lib.rs new file mode 100644 index 00000000..88bb55e5 --- /dev/null +++ b/contracts/libraries/icq-querier/src/lib.rs @@ -0,0 +1,4 @@ +pub mod contract; +pub mod msg; +#[cfg(test)] +mod testing; diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs new file mode 100644 index 00000000..25acbbc2 --- /dev/null +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -0,0 +1,65 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; + +use cosmwasm_std::{Addr, Deps, DepsMut}; +use cw_ownable::cw_ownable_query; +use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; +use valence_macros::{valence_library_query, ValenceLibraryInterface}; + +#[cw_serde] +pub enum FunctionMsgs {} + +#[valence_library_query] +#[cw_ownable_query] +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg {} + +#[cw_serde] +pub struct QuerierConfig {} + +#[cw_serde] +#[derive(ValenceLibraryInterface)] +pub struct LibraryConfig { + pub querier_config: QuerierConfig, +} + +impl LibraryConfig { + pub fn new(querier_config: QuerierConfig) -> Self { + LibraryConfig { querier_config } + } + + fn do_validate(&self, _api: &dyn cosmwasm_std::Api) -> Result<(), LibraryError> { + Ok(()) + } +} + +#[cw_serde] +/// Validated library configuration +pub struct Config { + pub querier_config: QuerierConfig, +} + +impl LibraryConfigValidation for LibraryConfig { + #[cfg(not(target_arch = "wasm32"))] + fn pre_validate(&self, api: &dyn cosmwasm_std::Api) -> Result<(), LibraryError> { + self.do_validate(api)?; + Ok(()) + } + + fn validate(&self, deps: Deps) -> Result { + self.do_validate(deps.api)?; + + Ok(Config { + querier_config: self.querier_config.clone(), + }) + } +} + +impl LibraryConfigUpdate { + pub fn update_config(self, deps: DepsMut) -> Result<(), LibraryError> { + let config: Config = valence_library_base::load_config(deps.storage)?; + // TODO + valence_library_base::save_config(deps.storage, &config)?; + Ok(()) + } +} diff --git a/contracts/libraries/icq-querier/src/testing/mod.rs b/contracts/libraries/icq-querier/src/testing/mod.rs new file mode 100644 index 00000000..87c27719 --- /dev/null +++ b/contracts/libraries/icq-querier/src/testing/mod.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +mod tests; diff --git a/contracts/libraries/icq-querier/src/testing/tests.rs b/contracts/libraries/icq-querier/src/testing/tests.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/contracts/libraries/icq-querier/src/testing/tests.rs @@ -0,0 +1 @@ + From 832adfe703fd1cba13e121cb77a095049d54fd3b Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 27 Nov 2024 17:38:52 +0100 Subject: [PATCH 50/92] wip --- Cargo.lock | 2 ++ contracts/libraries/icq-querier/Cargo.toml | 2 ++ contracts/libraries/icq-querier/src/lib.rs | 2 ++ contracts/libraries/icq-querier/src/msg.rs | 10 +++++++++- contracts/libraries/icq-querier/src/utils/mod.rs | 1 + contracts/libraries/icq-querier/src/utils/types.rs | 1 + 6 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 contracts/libraries/icq-querier/src/utils/mod.rs create mode 100644 contracts/libraries/icq-querier/src/utils/types.rs diff --git a/Cargo.lock b/Cargo.lock index 12c3ce10..6e05971a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5222,6 +5222,8 @@ dependencies = [ "cw20 2.0.0", "osmosis-std", "osmosis-test-tube", + "prost 0.13.3", + "prost-types 0.13.3", "valence-account-utils", "valence-library-base", "valence-library-utils", diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index cb5b2912..5e175f9b 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -23,6 +23,8 @@ valence-library-base = { workspace = true } osmosis-std = { workspace = true } valence-account-utils = { workspace = true } valence-osmosis-utils = { workspace = true } +prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } +prost-types = { version = "0.13.3", default-features = false } [dev-dependencies] cw20 = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/lib.rs b/contracts/libraries/icq-querier/src/lib.rs index 88bb55e5..5a12d490 100644 --- a/contracts/libraries/icq-querier/src/lib.rs +++ b/contracts/libraries/icq-querier/src/lib.rs @@ -2,3 +2,5 @@ pub mod contract; pub mod msg; #[cfg(test)] mod testing; + +pub mod utils; diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index 25acbbc2..afcc6393 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -6,7 +6,15 @@ use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; use valence_macros::{valence_library_query, ValenceLibraryInterface}; #[cw_serde] -pub enum FunctionMsgs {} +pub enum FunctionMsgs { + RegisterKvQuery { + connection_id: String, + update_period: u64, + // TODO: enum + module: String, + // + }, +} #[valence_library_query] #[cw_ownable_query] diff --git a/contracts/libraries/icq-querier/src/utils/mod.rs b/contracts/libraries/icq-querier/src/utils/mod.rs new file mode 100644 index 00000000..cd408564 --- /dev/null +++ b/contracts/libraries/icq-querier/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/contracts/libraries/icq-querier/src/utils/types.rs b/contracts/libraries/icq-querier/src/utils/types.rs new file mode 100644 index 00000000..473368c0 --- /dev/null +++ b/contracts/libraries/icq-querier/src/utils/types.rs @@ -0,0 +1 @@ +use std::collections::HashMap; From 53ef99f5ab1b8271bb9e332fd3b2e8be904610fc Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 28 Nov 2024 12:13:07 +0100 Subject: [PATCH 51/92] handling sudo response --- Cargo.lock | 5 + contracts/libraries/icq-querier/Cargo.toml | 4 + .../libraries/icq-querier/src/contract.rs | 178 ++++++++++++++-- contracts/libraries/icq-querier/src/error.rs | 27 +++ contracts/libraries/icq-querier/src/lib.rs | 2 + contracts/libraries/icq-querier/src/msg.rs | 14 +- contracts/libraries/icq-querier/src/state.rs | 6 + local-interchaintest/Cargo.toml | 1 + .../examples/interchain_querier.rs | 190 ++++++++++++++++++ 9 files changed, 406 insertions(+), 21 deletions(-) create mode 100644 contracts/libraries/icq-querier/src/error.rs create mode 100644 contracts/libraries/icq-querier/src/state.rs create mode 100644 local-interchaintest/examples/interchain_querier.rs diff --git a/Cargo.lock b/Cargo.lock index 6e05971a..030cd80f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2568,6 +2568,7 @@ dependencies = [ "valence-forwarder-library", "valence-generic-ibc-transfer-library", "valence-ibc-utils", + "valence-icq-querier", "valence-library-utils", "valence-neutron-ibc-transfer-library", "valence-osmosis-cl-lper", @@ -5219,11 +5220,15 @@ dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "cw-ownable", + "cw-storage-plus 2.0.0", "cw20 2.0.0", + "neutron-sdk", "osmosis-std", "osmosis-test-tube", "prost 0.13.3", "prost-types 0.13.3", + "serde-json-wasm 1.0.1", + "thiserror 1.0.69", "valence-account-utils", "valence-library-base", "valence-library-utils", diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 5e175f9b..3bdf8162 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -25,6 +25,10 @@ valence-account-utils = { workspace = true } valence-osmosis-utils = { workspace = true } prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } prost-types = { version = "0.13.3", default-features = false } +neutron-sdk = { workspace = true } +serde-json-wasm = { version = "1.0.0", default-features = false } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] cw20 = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 3bbc31cb..0ab9a8b2 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -1,35 +1,91 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; -use valence_library_utils::{ - error::LibraryError, - msg::{ExecuteMsg, InstantiateMsg}, +use cosmwasm_std::{ + to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Order, Reply, + Response, StdError, StdResult, SubMsg, }; +use neutron_sdk::{ + bindings::{ + msg::{MsgRegisterInterchainQueryResponse, NeutronMsg}, + query::NeutronQuery, + types::KVKey, + }, + interchain_queries::{queries::get_raw_interchain_query_result, types::QueryType}, + sudo::msg::SudoMsg, +}; +use valence_library_utils::error::LibraryError; -use crate::msg::{Config, FunctionMsgs, LibraryConfig, LibraryConfigUpdate, QueryMsg}; +use crate::{ + error::ContractError, + msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, LibraryConfigUpdate, QueryMsg}, + state::{ASSOCIATED_QUERY_IDS, LOGS, QUERY_RESULTS}, +}; // version info for migration info -const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +const GAMM_QUERY_REGISTRATION_REPLY_ID: u64 = 31415; + +pub type QueryDeps<'a> = Deps<'a, NeutronQuery>; +pub type ExecuteDeps<'a> = DepsMut<'a, NeutronQuery>; #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - deps: DepsMut, + _deps: DepsMut, _env: Env, _info: MessageInfo, - msg: InstantiateMsg, -) -> Result { - valence_library_base::instantiate(deps, CONTRACT_NAME, CONTRACT_VERSION, msg) + msg: InstantiateMsg, +) -> Result, LibraryError> { + // valence_library_base::instantiate(deps, CONTRACT_NAME, CONTRACT_VERSION, msg) + Ok(Response::default()) } #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: ExecuteMsg, -) -> Result { - valence_library_base::execute(deps, env, info, msg, process_function, update_config) + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: FunctionMsgs, +) -> Result, LibraryError> { + // valence_library_base::execute(deps, env, info, msg, process_function, update_config) + match msg { + FunctionMsgs::RegisterKvQuery { + connection_id, + update_period, + module, + } => register_kv_query(connection_id, update_period, module), + } +} + +fn register_kv_query( + connection_id: String, + update_period: u64, + path: String, // aka module, e.g. gamm +) -> Result, LibraryError> { + let pool_prefix_key: u8 = 0x02; + let pool_id: u64 = 1; + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); + + let kv_key = KVKey { + path, + key: Binary::new(pool_access_key), + }; + + let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { + query_type: QueryType::KV.into(), + keys: vec![kv_key], + transactions_filter: String::new(), + connection_id, + update_period, + }; + + // fire registration in a submsg to get the registered query id back + // TODO: remove hardcoded reply_id and obtain it above based on args + let submsg = SubMsg::reply_on_success(kv_registration_msg, GAMM_QUERY_REGISTRATION_REPLY_ID); + + Ok(Response::default().add_submessage(submsg)) } pub fn update_config( @@ -45,9 +101,9 @@ pub fn process_function( deps: DepsMut, _env: Env, _info: MessageInfo, - msg: FunctionMsgs, - cfg: Config, -) -> Result { + _msg: FunctionMsgs, + _cfg: Config, +) -> Result, LibraryError> { Ok(Response::default()) } @@ -69,5 +125,87 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { valence_library_utils::raw_config::query_raw_library_config(deps.storage)?; to_json_binary(&raw_config) } + QueryMsg::RegisteredQueries {} => { + let mut resp = vec![]; + for entry in ASSOCIATED_QUERY_IDS.range(deps.storage, None, None, Order::Ascending) { + resp.push(entry?); + } + to_json_binary(&resp) + } + QueryMsg::Logs {} => { + let mut resp = vec![]; + for entry in LOGS.range(deps.storage, None, None, Order::Ascending) { + resp.push(entry?); + } + to_json_binary(&resp) + } + QueryMsg::QueryResults {} => { + let mut resp = vec![]; + for entry in QUERY_RESULTS.range(deps.storage, None, None, Order::Ascending) { + resp.push(entry?); + } + to_json_binary(&resp) + } } } + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult> { + match msg { + SudoMsg::KVQueryResult { query_id } => handle_sudo_kv_query_result(deps, query_id), + _ => { + LOGS.save( + deps.storage, + format!("sudo_catchall_handler-{}", env.block.height).to_string(), + &to_json_string(&msg)?, + )?; + Ok(Response::default()) + } + } +} + +fn handle_sudo_kv_query_result( + deps: ExecuteDeps, + query_id: u64, +) -> StdResult> { + let registered_query_result = get_raw_interchain_query_result(deps.as_ref(), query_id) + .map_err(|_| StdError::generic_err("failed to get the raw icq result"))?; + + let query_result_str = to_json_string(®istered_query_result.result)?; + + QUERY_RESULTS.save(deps.storage, query_id, &query_result_str)?; + + Ok(Response::new().add_attribute("query_result", query_result_str)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn reply(deps: DepsMut, _: Env, msg: Reply) -> StdResult { + match msg.id { + GAMM_QUERY_REGISTRATION_REPLY_ID => try_associate_registered_query_id(deps, msg), + _ => Err(ContractError::UnknownReplyId(msg.id).into()), + } +} + +fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult { + let submsg_response = reply.result.into_result().map_err(StdError::generic_err)?; + + // response.data is deprecated + // TODO: look into whether it's possible to use the cw2.0 method + #[allow(deprecated)] + let binary = submsg_response + .data + .ok_or_else(|| StdError::generic_err("no data in reply"))?; + + let resp: MsgRegisterInterchainQueryResponse = + serde_json_wasm::from_slice(binary.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + LOGS.save( + deps.storage, + format!("registered_query_type_{GAMM_QUERY_REGISTRATION_REPLY_ID}"), + &reply.id.to_string(), + )?; + ASSOCIATED_QUERY_IDS.save(deps.storage, resp.id, &"gamm".to_string())?; + + Ok(Response::default()) +} diff --git a/contracts/libraries/icq-querier/src/error.rs b/contracts/libraries/icq-querier/src/error.rs new file mode 100644 index 00000000..57de7ae5 --- /dev/null +++ b/contracts/libraries/icq-querier/src/error.rs @@ -0,0 +1,27 @@ +use cosmwasm_std::StdError; +use thiserror::Error; +use valence_library_utils::error::LibraryError; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unknown reply id: {0}")] + UnknownReplyId(u64), +} + +impl From for StdError { + fn from(val: ContractError) -> Self { + match val { + ContractError::Std(std_error) => std_error, + e => StdError::generic_err(e.to_string()), + } + } +} + +impl From for LibraryError { + fn from(val: ContractError) -> Self { + LibraryError::Std(val.into()) + } +} diff --git a/contracts/libraries/icq-querier/src/lib.rs b/contracts/libraries/icq-querier/src/lib.rs index 5a12d490..98098cd8 100644 --- a/contracts/libraries/icq-querier/src/lib.rs +++ b/contracts/libraries/icq-querier/src/lib.rs @@ -3,4 +3,6 @@ pub mod msg; #[cfg(test)] mod testing; +pub mod error; +pub mod state; pub mod utils; diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index afcc6393..a4383381 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -5,6 +5,9 @@ use cw_ownable::cw_ownable_query; use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; use valence_macros::{valence_library_query, ValenceLibraryInterface}; +#[cw_serde] +pub struct InstantiateMsg {} + #[cw_serde] pub enum FunctionMsgs { RegisterKvQuery { @@ -20,7 +23,16 @@ pub enum FunctionMsgs { #[cw_ownable_query] #[cw_serde] #[derive(QueryResponses)] -pub enum QueryMsg {} +pub enum QueryMsg { + #[returns(Vec<(String, String)>)] + Logs {}, + + #[returns(Vec<(u64, String)>)] + RegisteredQueries {}, + + #[returns(Vec<(u64, String)>)] + QueryResults {}, +} #[cw_serde] pub struct QuerierConfig {} diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs new file mode 100644 index 00000000..441f654c --- /dev/null +++ b/contracts/libraries/icq-querier/src/state.rs @@ -0,0 +1,6 @@ +use cw_storage_plus::Map; + +pub const LOGS: Map = Map::new("logs"); +pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); + +pub const QUERY_RESULTS: Map = Map::new("query_results"); diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index bccf79f7..a061cdee 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -47,3 +47,4 @@ tokio = { workspace = true } osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } +valence-icq-querier = { workspace = true } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs new file mode 100644 index 00000000..01f6d481 --- /dev/null +++ b/local-interchaintest/examples/interchain_querier.rs @@ -0,0 +1,190 @@ +use local_interchaintest::utils::{ + icq::{generate_icq_relayer_config, start_icq_relayer}, + osmosis::gamm::setup_gamm_pool, + LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, +}; +use localic_std::{ + errors::LocalError, + modules::cosmwasm::{contract_execute, contract_instantiate, contract_query}, + types::TransactionResponse, +}; +use log::info; +use std::{env, error::Error, time::Duration}; +use valence_icq_querier::msg::{FunctionMsgs, InstantiateMsg, QueryMsg}; + +use localic_utils::{ + utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, + LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, + OSMOSIS_CHAIN_NAME, +}; + +// KeyNextGlobalPoolId defines key to store the next Pool ID to be used. +pub const NEXT_GLOBAL_POOL_ID_KEY: u8 = 0x01; +pub const PREFIX_POOLS_KEY: u8 = 0x02; +pub const TOTAL_LIQUIDITY_KEY: u8 = 0x03; +pub const PREFIX_MIGRATION_INFO_BALANCER_POOL_KEY: u8 = 0x04; +pub const GAMM_STORE_KEY: &str = "gamm"; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let mut test_ctx = TestContextBuilder::default() + .with_unwrap_raw_logs(true) + .with_api_url(LOCAL_IC_API_URL) + .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) + .with_chain(ConfigChainBuilder::default_neutron().build()?) + .with_chain(ConfigChainBuilder::default_osmosis().build()?) + .with_chain(ConfigChainBuilder::default_gaia().build()?) + .with_log_file_path(LOGS_FILE_PATH) + .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) + .build()?; + + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + + let current_dir = env::current_dir()?; + + // with test context set up, we can generate the .env file for the icq relayer + generate_icq_relayer_config( + &test_ctx, + current_dir.clone(), + OSMOSIS_CHAIN_NAME.to_string(), + )?; + + // start the icq relayer. this runs in detached mode so we need + // to manually kill it before each run for now. + start_icq_relayer()?; + + let mut uploader = test_ctx.build_tx_upload_contracts(); + let icq_lib_local_path = format!( + "{}/artifacts/valence_icq_querier.wasm", + current_dir.display() + ); + + info!("sleeping to allow icq relayer to start..."); + std::thread::sleep(Duration::from_secs(10)); + + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&icq_lib_local_path)?; + + let icq_querier_lib_code_id = test_ctx + .get_contract() + .contract("valence_icq_querier") + .get_cw() + .code_id + .unwrap(); + + info!("icq querier library code id: {icq_querier_lib_code_id}"); + + // instantiate icq querier lib + let icq_test_lib = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + icq_querier_lib_code_id, + &serde_json::to_string(&InstantiateMsg {})?, + "icq_querier_lib", + None, + "", + )?; + + info!("icq querier lib address: {}", icq_test_lib.address); + + info!("attempting GAMM total liquidity query"); + + let kvq_registration_response = register_kvq( + &test_ctx, + icq_test_lib.address.to_string(), + OSMOSIS_CHAIN_NAME.to_string(), + )?; + + info!( + "kv query registration response: {:?}", + kvq_registration_response + ); + + std::thread::sleep(Duration::from_secs(5)); + + let logs = query_logs(&test_ctx, icq_test_lib.address.to_string())?; + info!("logs: {:?}", logs); + + let results = query_results(&test_ctx, icq_test_lib.address.to_string())?; + info!("results: {:?}", results); + + Ok(()) +} + +pub fn register_kvq( + test_ctx: &TestContext, + icq_lib: String, + domain: String, +) -> Result { + info!("registering ICQ KV query on domain {domain}..."); + + let register_kvq_msg = FunctionMsgs::RegisterKvQuery { + connection_id: test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(&domain) + .get(), + update_period: 5, + module: "gamm".to_string(), + }; + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &serde_json::to_string(®ister_kvq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + "--amount 1000000untrn --gas 50000000", + ) +} + +pub fn query_logs( + test_ctx: &TestContext, + icq_lib: String, +) -> Result, LocalError> { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::Logs {}) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let resp: Vec<(String, String)> = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} + +pub fn query_results( + test_ctx: &TestContext, + icq_lib: String, +) -> Result, LocalError> { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&QueryMsg::QueryResults {}) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + let resp: Vec<(u64, String)> = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} From 5e786fb1300427aab9627a77e3005c4b00715ba5 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 28 Nov 2024 13:26:37 +0100 Subject: [PATCH 52/92] init query type enums --- .../libraries/icq-querier/src/contract.rs | 105 +++++++++++++++--- contracts/libraries/icq-querier/src/error.rs | 3 + contracts/libraries/icq-querier/src/msg.rs | 16 +++ contracts/libraries/icq-querier/src/state.rs | 4 +- .../libraries/icq-querier/src/utils/types.rs | 2 +- contracts/testing/test-icq-lib/src/icq.rs | 31 +++++- .../examples/interchain_querier.rs | 22 +++- 7 files changed, 156 insertions(+), 27 deletions(-) diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 0ab9a8b2..789c7c44 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -10,14 +10,23 @@ use neutron_sdk::{ query::NeutronQuery, types::KVKey, }, - interchain_queries::{queries::get_raw_interchain_query_result, types::QueryType}, + interchain_queries::{ + helpers::decode_and_convert, + queries::get_raw_interchain_query_result, + types::{KVReconstruct, QueryType}, + v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, + }, sudo::msg::SudoMsg, }; +use prost::Message; use valence_library_utils::error::LibraryError; use crate::{ error::ContractError, - msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, LibraryConfigUpdate, QueryMsg}, + msg::{ + BankResultTypes, Config, FunctionMsgs, GammResultTypes, InstantiateMsg, LibraryConfig, + LibraryConfigUpdate, QueryMsg, QueryResult, + }, state::{ASSOCIATED_QUERY_IDS, LOGS, QUERY_RESULTS}, }; @@ -26,6 +35,7 @@ const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); const GAMM_QUERY_REGISTRATION_REPLY_ID: u64 = 31415; +const BANK_QUERY_REGISTRATION_REPLY_ID: u64 = 31416; pub type QueryDeps<'a> = Deps<'a, NeutronQuery>; pub type ExecuteDeps<'a> = DepsMut<'a, NeutronQuery>; @@ -35,7 +45,7 @@ pub fn instantiate( _deps: DepsMut, _env: Env, _info: MessageInfo, - msg: InstantiateMsg, + _msg: InstantiateMsg, ) -> Result, LibraryError> { // valence_library_base::instantiate(deps, CONTRACT_NAME, CONTRACT_VERSION, msg) Ok(Response::default()) @@ -63,14 +73,36 @@ fn register_kv_query( update_period: u64, path: String, // aka module, e.g. gamm ) -> Result, LibraryError> { - let pool_prefix_key: u8 = 0x02; - let pool_id: u64 = 1; - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); - - let kv_key = KVKey { - path, - key: Binary::new(pool_access_key), + let (kv_key, response_code_id) = match path.as_str() { + "gamm" => { + let pool_prefix_key: u8 = 0x02; + let pool_id: u64 = 1; + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); + + ( + KVKey { + path, + key: Binary::new(pool_access_key), + }, + GAMM_QUERY_REGISTRATION_REPLY_ID, + ) + } + "bank" => { + let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; + let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + let balance_key = + create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); + + ( + KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }, + BANK_QUERY_REGISTRATION_REPLY_ID, + ) + } + _ => return Err(ContractError::UnsupportedModule(path).into()), }; let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { @@ -82,8 +114,7 @@ fn register_kv_query( }; // fire registration in a submsg to get the registered query id back - // TODO: remove hardcoded reply_id and obtain it above based on args - let submsg = SubMsg::reply_on_success(kv_registration_msg, GAMM_QUERY_REGISTRATION_REPLY_ID); + let submsg = SubMsg::reply_on_success(kv_registration_msg, response_code_id); Ok(Response::default().add_submessage(submsg)) } @@ -98,7 +129,7 @@ pub fn update_config( } pub fn process_function( - deps: DepsMut, + _deps: DepsMut, _env: Env, _info: MessageInfo, _msg: FunctionMsgs, @@ -171,7 +202,33 @@ fn handle_sudo_kv_query_result( let registered_query_result = get_raw_interchain_query_result(deps.as_ref(), query_id) .map_err(|_| StdError::generic_err("failed to get the raw icq result"))?; - let query_result_str = to_json_string(®istered_query_result.result)?; + let associated_query_type = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; + let query_result_str = match associated_query_type { + QueryResult::Gamm { result_type } => match result_type { + GammResultTypes::Pool => { + let any_msg: osmosis_std::shim::Any = osmosis_std::shim::Any::decode( + registered_query_result.result.kv_results[0] + .value + .as_slice(), + ) + .unwrap(); + assert_eq!(any_msg.type_url, "/osmosis.gamm.v1beta1.Pool"); + + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = + any_msg.try_into().unwrap(); + + to_json_string(&osmo_pool).unwrap() + } + }, + QueryResult::Bank { result_type } => match result_type { + BankResultTypes::AccountDenomBalance => { + let balances: neutron_sdk::interchain_queries::v047::types::Balances = + KVReconstruct::reconstruct(®istered_query_result.result.kv_results).unwrap(); + + to_json_string(&balances).unwrap() + } + }, + }; QUERY_RESULTS.save(deps.storage, query_id, &query_result_str)?; @@ -181,7 +238,9 @@ fn handle_sudo_kv_query_result( #[cfg_attr(not(feature = "library"), entry_point)] pub fn reply(deps: DepsMut, _: Env, msg: Reply) -> StdResult { match msg.id { - GAMM_QUERY_REGISTRATION_REPLY_ID => try_associate_registered_query_id(deps, msg), + GAMM_QUERY_REGISTRATION_REPLY_ID | BANK_QUERY_REGISTRATION_REPLY_ID => { + try_associate_registered_query_id(deps, msg) + } _ => Err(ContractError::UnknownReplyId(msg.id).into()), } } @@ -202,10 +261,20 @@ fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult QueryResult::Gamm { + result_type: GammResultTypes::Pool, + }, + BANK_QUERY_REGISTRATION_REPLY_ID => QueryResult::Bank { + result_type: BankResultTypes::AccountDenomBalance, + }, + _ => return Err(ContractError::UnknownReplyId(reply.id).into()), + }; + ASSOCIATED_QUERY_IDS.save(deps.storage, resp.id, &val_type)?; Ok(Response::default()) } diff --git a/contracts/libraries/icq-querier/src/error.rs b/contracts/libraries/icq-querier/src/error.rs index 57de7ae5..9c48c426 100644 --- a/contracts/libraries/icq-querier/src/error.rs +++ b/contracts/libraries/icq-querier/src/error.rs @@ -9,6 +9,9 @@ pub enum ContractError { #[error("Unknown reply id: {0}")] UnknownReplyId(u64), + + #[error("Unsupported module: {0}")] + UnsupportedModule(String), } impl From for StdError { diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index a4383381..f501d4c5 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -5,6 +5,22 @@ use cw_ownable::cw_ownable_query; use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; use valence_macros::{valence_library_query, ValenceLibraryInterface}; +#[cw_serde] +pub enum QueryResult { + Gamm { result_type: GammResultTypes }, + Bank { result_type: BankResultTypes }, +} + +#[cw_serde] +pub enum GammResultTypes { + Pool, +} + +#[cw_serde] +pub enum BankResultTypes { + AccountDenomBalance, +} + #[cw_serde] pub struct InstantiateMsg {} diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index 441f654c..e3f67906 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -1,6 +1,8 @@ use cw_storage_plus::Map; +use crate::msg::QueryResult; + pub const LOGS: Map = Map::new("logs"); -pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); +pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); pub const QUERY_RESULTS: Map = Map::new("query_results"); diff --git a/contracts/libraries/icq-querier/src/utils/types.rs b/contracts/libraries/icq-querier/src/utils/types.rs index 473368c0..8b137891 100644 --- a/contracts/libraries/icq-querier/src/utils/types.rs +++ b/contracts/libraries/icq-querier/src/utils/types.rs @@ -1 +1 @@ -use std::collections::HashMap; + diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index f3c3776a..086dd487 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -231,16 +231,19 @@ pub fn register_kv_query( #[cfg(test)] mod test { - use cosmwasm_std::{to_json_string, Binary}; - use neutron_sdk::bindings::types::StorageValue; + use cosmwasm_std::{from_json, to_json_string, Binary, Uint128}; + use neutron_sdk::{ + bindings::types::StorageValue, + interchain_queries::{query_kv_result, types::KVReconstruct}, + }; use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; use prost::Message; use serde_json::Value; #[test] fn try_decode_osmo_pool_from_binary() { - let key_utf8 = "\u{2}\0\0\0\0\0\0\0\u{1}"; - let binary_key = Binary::from(key_utf8.as_bytes()); + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; let binary_value = Binary::from_base64(b64_value).unwrap(); @@ -263,4 +266,24 @@ mod test { let json_value: Value = serde_json::from_str(&json_str).unwrap(); println!("json value: {:?}", json_value); } + + #[test] + fn try_decode_balance_response_from_binary() { + let b64_key = "AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "OTk5NjY5OTk5MjUwMA=="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "bank".to_string(), + key: binary_key, + value: binary_value, + }; + + let balances: neutron_sdk::interchain_queries::v047::types::Balances = + KVReconstruct::reconstruct(&vec![storage_value]).unwrap(); + + println!("balances: {:?}", balances); + } } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index 01f6d481..5d531fa4 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -46,7 +46,7 @@ fn main() -> Result<(), Box> { .dest(OSMOSIS_CHAIN_NAME) .get(); - let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + let _pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; let current_dir = env::current_dir()?; @@ -104,6 +104,21 @@ fn main() -> Result<(), Box> { &test_ctx, icq_test_lib.address.to_string(), OSMOSIS_CHAIN_NAME.to_string(), + "gamm".to_string(), + )?; + + info!( + "kv query registration response: {:?}", + kvq_registration_response + ); + + std::thread::sleep(Duration::from_secs(5)); + + let kvq_registration_response = register_kvq( + &test_ctx, + icq_test_lib.address.to_string(), + OSMOSIS_CHAIN_NAME.to_string(), + "bank".to_string(), )?; info!( @@ -126,8 +141,9 @@ pub fn register_kvq( test_ctx: &TestContext, icq_lib: String, domain: String, + module: String, ) -> Result { - info!("registering ICQ KV query on domain {domain}..."); + info!("registering ICQ KV query on domain {domain} for mod {module}..."); let register_kvq_msg = FunctionMsgs::RegisterKvQuery { connection_id: test_ctx @@ -136,7 +152,7 @@ pub fn register_kvq( .dest(&domain) .get(), update_period: 5, - module: "gamm".to_string(), + module, }; contract_execute( From 0896dc1ba87992ecae87736c3e10630fa74b0d01 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 28 Nov 2024 16:08:20 +0100 Subject: [PATCH 53/92] storing json value results instead of strings --- Cargo.lock | 1 + contracts/libraries/icq-querier/Cargo.toml | 1 + contracts/libraries/icq-querier/src/contract.rs | 12 +++++++++--- contracts/libraries/icq-querier/src/msg.rs | 10 +++++++++- contracts/libraries/icq-querier/src/state.rs | 6 +++--- local-interchaintest/examples/interchain_querier.rs | 5 +++-- 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 030cd80f..83600928 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5228,6 +5228,7 @@ dependencies = [ "prost 0.13.3", "prost-types 0.13.3", "serde-json-wasm 1.0.1", + "serde_json", "thiserror 1.0.69", "valence-account-utils", "valence-library-base", diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 3bdf8162..e2d93c4b 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -29,6 +29,7 @@ neutron-sdk = { workspace = true } serde-json-wasm = { version = "1.0.0", default-features = false } cw-storage-plus = { workspace = true } thiserror = { workspace = true } +serde_json = { workspace = true } [dev-dependencies] cw20 = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 789c7c44..17c44927 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -19,6 +19,7 @@ use neutron_sdk::{ sudo::msg::SudoMsg, }; use prost::Message; +use serde_json::Value; use valence_library_utils::error::LibraryError; use crate::{ @@ -176,7 +177,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { resp.push(entry?); } to_json_binary(&resp) - } + } // QueryMsg::AssertResultCondition { + // query_id, + // condition, + // } => assert_result_condition(deps, query_id, condition), } } @@ -230,9 +234,11 @@ fn handle_sudo_kv_query_result( }, }; - QUERY_RESULTS.save(deps.storage, query_id, &query_result_str)?; + let json_response: serde_json::Value = serde_json::from_str(&query_result_str).unwrap(); + + QUERY_RESULTS.save(deps.storage, query_id, &json_response)?; - Ok(Response::new().add_attribute("query_result", query_result_str)) + Ok(Response::new().add_attribute("query_result", json_response.to_string())) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index f501d4c5..258369ef 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -2,6 +2,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Deps, DepsMut}; use cw_ownable::cw_ownable_query; +use serde_json::Value; use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; use valence_macros::{valence_library_query, ValenceLibraryInterface}; @@ -46,8 +47,15 @@ pub enum QueryMsg { #[returns(Vec<(u64, String)>)] RegisteredQueries {}, - #[returns(Vec<(u64, String)>)] + #[returns(Vec<(u64, Value)>)] QueryResults {}, + // #[returns(bool)] + // AssertResultCondition { + // query_id: u64, + // path: String, + // operator: String, + // assertion_value: String, + // }, } #[cw_serde] diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index e3f67906..b48b4fc3 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -1,8 +1,8 @@ -use cw_storage_plus::Map; - use crate::msg::QueryResult; +use cw_storage_plus::Map; +use serde_json::Value; pub const LOGS: Map = Map::new("logs"); pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); -pub const QUERY_RESULTS: Map = Map::new("query_results"); +pub const QUERY_RESULTS: Map = Map::new("query_results"); diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index 5d531fa4..aa3f0baf 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -9,6 +9,7 @@ use localic_std::{ types::TransactionResponse, }; use log::info; +use serde_json::Value; use std::{env, error::Error, time::Duration}; use valence_icq_querier::msg::{FunctionMsgs, InstantiateMsg, QueryMsg}; @@ -189,7 +190,7 @@ pub fn query_logs( pub fn query_results( test_ctx: &TestContext, icq_lib: String, -) -> Result, LocalError> { +) -> Result, LocalError> { let query_response = contract_query( test_ctx .get_request_builder() @@ -200,7 +201,7 @@ pub fn query_results( )["data"] .clone(); - let resp: Vec<(u64, String)> = serde_json::from_value(query_response).unwrap(); + let resp: Vec<(u64, Value)> = serde_json::from_value(query_response).unwrap(); Ok(resp) } From 41f2e6aa16a60b7afdca1f056dc48bab1c19a94f Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 29 Nov 2024 15:49:18 +0100 Subject: [PATCH 54/92] wip: icq querier utils; domain specific type registries --- Cargo.lock | 48 ++++++ Cargo.toml | 5 + .../osmo_registry/Cargo.toml | 34 ++++ .../osmo_registry/src/contract.rs | 107 ++++++++++++ .../osmo_registry/src/error.rs | 23 +++ .../osmo_registry/src/lib.rs | 7 + .../osmo_registry/src/msg.rs | 17 ++ .../osmo_registry/src/state.rs | 3 + .../osmo_registry/src/testing/mod.rs | 1 + contracts/libraries/icq-querier/Cargo.toml | 2 + .../libraries/icq-querier/src/contract.rs | 153 +++++++----------- contracts/libraries/icq-querier/src/msg.rs | 15 +- contracts/libraries/icq-querier/src/state.rs | 13 +- contracts/testing/test-icq-lib/src/icq.rs | 9 +- local-interchaintest/Cargo.toml | 2 + .../examples/interchain_querier.rs | 58 +++++-- packages/icq-querier-utils/Cargo.toml | 38 +++++ packages/icq-querier-utils/src/lib.rs | 30 ++++ 18 files changed, 438 insertions(+), 127 deletions(-) create mode 100644 contracts/domain_type_registries/osmo_registry/Cargo.toml create mode 100644 contracts/domain_type_registries/osmo_registry/src/contract.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/error.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/lib.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/msg.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/state.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/testing/mod.rs create mode 100644 packages/icq-querier-utils/Cargo.toml create mode 100644 packages/icq-querier-utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 83600928..10286f6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2568,6 +2568,7 @@ dependencies = [ "valence-forwarder-library", "valence-generic-ibc-transfer-library", "valence-ibc-utils", + "valence-icq-lib-utils", "valence-icq-querier", "valence-library-utils", "valence-neutron-ibc-transfer-library", @@ -2575,6 +2576,7 @@ dependencies = [ "valence-osmosis-cl-withdrawer", "valence-osmosis-gamm-lper", "valence-osmosis-gamm-withdrawer", + "valence-osmosis-type-registry", "valence-osmosis-utils", "valence-processor", "valence-processor-utils", @@ -5213,6 +5215,29 @@ dependencies = [ "serde", ] +[[package]] +name = "valence-icq-lib-utils" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-denom", + "cw-multi-test", + "cw-ownable", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", + "cw20 2.0.0", + "cw20-base", + "neutron-sdk", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror 1.0.69", + "valence-account-utils", + "valence-base-account", + "valence-macros", +] + [[package]] name = "valence-icq-querier" version = "0.1.0" @@ -5231,9 +5256,11 @@ dependencies = [ "serde_json", "thiserror 1.0.69", "valence-account-utils", + "valence-icq-lib-utils", "valence-library-base", "valence-library-utils", "valence-macros", + "valence-osmosis-type-registry", "valence-osmosis-utils", ] @@ -5394,6 +5421,27 @@ dependencies = [ "valence-osmosis-utils", ] +[[package]] +name = "valence-osmosis-type-registry" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-ownable", + "cw-storage-plus 2.0.0", + "cw20 2.0.0", + "neutron-sdk", + "osmosis-std", + "osmosis-test-tube", + "prost 0.13.3", + "prost-types 0.13.3", + "serde-json-wasm 1.0.1", + "serde_json", + "thiserror 1.0.69", + "valence-icq-lib-utils", + "valence-osmosis-utils", +] + [[package]] name = "valence-osmosis-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8d57bcc5..d315ab10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "contracts/processor", "contracts/testing/*", "contracts/program-registry", + "contracts/domain_type_registries/*", "packages/*", "program-manager", "local-interchaintest", @@ -87,6 +88,10 @@ valence-library-utils = { path = "packages/library-utils" } valence-program-registry-utils = { path = "packages/program-registry-utils" } valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } +valence-icq-lib-utils = { path = "packages/icq-querier-utils" } + +# domain type registries +valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } # dev-dependencies cw-multi-test = { version = "2.1.1", features = ["cosmwasm_1_4"] } diff --git a/contracts/domain_type_registries/osmo_registry/Cargo.toml b/contracts/domain_type_registries/osmo_registry/Cargo.toml new file mode 100644 index 00000000..c741db58 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "valence-osmosis-type-registry" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +version = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-ownable = { workspace = true } +osmosis-std = { workspace = true } +valence-osmosis-utils = { workspace = true } +prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } +prost-types = { version = "0.13.3", default-features = false } +neutron-sdk = { workspace = true } +serde-json-wasm = { version = "1.0.0", default-features = false } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } +serde_json = { workspace = true } +valence-icq-lib-utils = { workspace = true } + +[dev-dependencies] +cw20 = { workspace = true } +osmosis-test-tube = { workspace = true } +valence-osmosis-utils = { workspace = true, features = ["testing"] } diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs new file mode 100644 index 00000000..3c3f318f --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -0,0 +1,107 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use neutron_sdk::bindings::msg::NeutronMsg; +use neutron_sdk::bindings::types::KVKey; +use neutron_sdk::interchain_queries::helpers::decode_and_convert; +use neutron_sdk::interchain_queries::types::QueryType; +use neutron_sdk::interchain_queries::v047::helpers::create_account_denom_balance_key; +use neutron_sdk::interchain_queries::v047::types::BANK_STORE_KEY; +use valence_icq_lib_utils::QueryRegistrationInfoRequest; +use valence_icq_lib_utils::QueryRegistrationInfoResponse; + +use crate::error::ContractError; +use crate::state::CONNECTION_ID; + +use valence_icq_lib_utils::ExecuteMsg as DomainRegistryExecuteMsg; +use valence_icq_lib_utils::InstantiateMsg as DomainRegistryInstantiateMsg; +use valence_icq_lib_utils::QueryMsg as DomainRegistryQueryMsg; + +// version info for migration info +const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +const GAMM_QUERY_REGISTRATION_REPLY_ID: u64 = 31415; +const BANK_QUERY_REGISTRATION_REPLY_ID: u64 = 31416; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: DomainRegistryInstantiateMsg, +) -> Result { + CONNECTION_ID.save(deps.storage, &msg.connection_id)?; + + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: DomainRegistryExecuteMsg, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: DomainRegistryQueryMsg) -> StdResult { + match msg { + DomainRegistryQueryMsg::GetRegistrationConfig(request) => { + get_registration_config(deps, request) + } + } +} + +fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> StdResult { + let (kv_key, response_code_id) = match query.module.as_str() { + "gamm" => { + let pool_prefix_key: u8 = 0x02; + let pool_id: u64 = 1; + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); + + ( + KVKey { + path: query.module.to_string(), + key: Binary::new(pool_access_key), + }, + GAMM_QUERY_REGISTRATION_REPLY_ID, + ) + } + "bank" => { + let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63".to_string(); + let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + let balance_key = + create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); + + ( + KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }, + BANK_QUERY_REGISTRATION_REPLY_ID, + ) + } + _ => return Err(ContractError::UnsupportedModule(query.module).into()), + }; + + let connection_id = CONNECTION_ID.load(deps.storage)?; + + let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { + query_type: QueryType::KV.into(), + keys: vec![kv_key], + transactions_filter: String::new(), + connection_id, + update_period: 5, + }; + + let query = QueryRegistrationInfoResponse { + registration_msg: kv_registration_msg, + reply_id: response_code_id, + }; + + to_json_binary(&query) +} diff --git a/contracts/domain_type_registries/osmo_registry/src/error.rs b/contracts/domain_type_registries/osmo_registry/src/error.rs new file mode 100644 index 00000000..51835b73 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/error.rs @@ -0,0 +1,23 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unknown reply id: {0}")] + UnknownReplyId(u64), + + #[error("Unsupported module: {0}")] + UnsupportedModule(String), +} + +impl From for StdError { + fn from(val: ContractError) -> Self { + match val { + ContractError::Std(std_error) => std_error, + e => StdError::generic_err(e.to_string()), + } + } +} diff --git a/contracts/domain_type_registries/osmo_registry/src/lib.rs b/contracts/domain_type_registries/osmo_registry/src/lib.rs new file mode 100644 index 00000000..3274df2d --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/lib.rs @@ -0,0 +1,7 @@ +pub mod contract; +pub mod msg; +#[cfg(test)] +mod testing; + +pub mod error; +pub mod state; diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs new file mode 100644 index 00000000..3df6ece6 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -0,0 +1,17 @@ +use cosmwasm_schema::cw_serde; + +#[cw_serde] +pub enum QueryResult { + Gamm { result_type: GammResultTypes }, + Bank { result_type: BankResultTypes }, +} + +#[cw_serde] +pub enum GammResultTypes { + Pool, +} + +#[cw_serde] +pub enum BankResultTypes { + AccountDenomBalance, +} diff --git a/contracts/domain_type_registries/osmo_registry/src/state.rs b/contracts/domain_type_registries/osmo_registry/src/state.rs new file mode 100644 index 00000000..04982b18 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/state.rs @@ -0,0 +1,3 @@ +use cw_storage_plus::Item; + +pub const CONNECTION_ID: Item = Item::new("connection_id"); diff --git a/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs b/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs @@ -0,0 +1 @@ + diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index e2d93c4b..9640b325 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -30,6 +30,8 @@ serde-json-wasm = { version = "1.0.0", default-features = false } cw-storage-plus = { workspace = true } thiserror = { workspace = true } serde_json = { workspace = true } +valence-osmosis-type-registry = { workspace = true } +valence-icq-lib-utils = { workspace = true } [dev-dependencies] cw20 = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 17c44927..e6e1b923 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -8,36 +8,33 @@ use neutron_sdk::{ bindings::{ msg::{MsgRegisterInterchainQueryResponse, NeutronMsg}, query::NeutronQuery, - types::KVKey, - }, - interchain_queries::{ - helpers::decode_and_convert, - queries::get_raw_interchain_query_result, - types::{KVReconstruct, QueryType}, - v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, }, + interchain_queries::{queries::get_raw_interchain_query_result, types::KVReconstruct}, sudo::msg::SudoMsg, }; use prost::Message; -use serde_json::Value; +use valence_icq_lib_utils::QueryMsg as DomainRegistryQueryMsg; +use valence_icq_lib_utils::QueryRegistrationInfoRequest as DomainRegistryQueryRequest; + +use valence_icq_lib_utils::QueryRegistrationInfoResponse; use valence_library_utils::error::LibraryError; use crate::{ error::ContractError, msg::{ BankResultTypes, Config, FunctionMsgs, GammResultTypes, InstantiateMsg, LibraryConfig, - LibraryConfigUpdate, QueryMsg, QueryResult, + QueryMsg, QueryResult, + }, + state::{ + PendingQueryIdConfig, ASSOCIATED_QUERY_IDS, LOGS, QUERY_REGISTRATION_REPLY_IDS, + QUERY_RESULTS, }, - state::{ASSOCIATED_QUERY_IDS, LOGS, QUERY_RESULTS}, }; // version info for migration info const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -const GAMM_QUERY_REGISTRATION_REPLY_ID: u64 = 31415; -const BANK_QUERY_REGISTRATION_REPLY_ID: u64 = 31416; - pub type QueryDeps<'a> = Deps<'a, NeutronQuery>; pub type ExecuteDeps<'a> = DepsMut<'a, NeutronQuery>; @@ -54,7 +51,7 @@ pub fn instantiate( #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( - _deps: DepsMut, + deps: DepsMut, _env: Env, _info: MessageInfo, msg: FunctionMsgs, @@ -62,83 +59,56 @@ pub fn execute( // valence_library_base::execute(deps, env, info, msg, process_function, update_config) match msg { FunctionMsgs::RegisterKvQuery { - connection_id, - update_period, + type_registry, module, - } => register_kv_query(connection_id, update_period, module), + query, + } => register_kv_query(deps, type_registry, module, query), } } fn register_kv_query( - connection_id: String, - update_period: u64, - path: String, // aka module, e.g. gamm + deps: DepsMut, + type_registry: String, + module: String, + query: String, ) -> Result, LibraryError> { - let (kv_key, response_code_id) = match path.as_str() { - "gamm" => { - let pool_prefix_key: u8 = 0x02; - let pool_id: u64 = 1; - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); - - ( - KVKey { - path, - key: Binary::new(pool_access_key), - }, - GAMM_QUERY_REGISTRATION_REPLY_ID, - ) - } - "bank" => { - let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"; - let converted_addr_bytes = decode_and_convert(&addr).unwrap(); - let balance_key = - create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); + let query_registration_resp: QueryRegistrationInfoResponse = deps.querier.query_wasm_smart( + type_registry.to_string(), + &DomainRegistryQueryMsg::GetRegistrationConfig(DomainRegistryQueryRequest { + module: module.to_string(), + query, + }), + )?; - ( - KVKey { - path: BANK_STORE_KEY.to_string(), - key: Binary::new(balance_key), - }, - BANK_QUERY_REGISTRATION_REPLY_ID, - ) - } - _ => return Err(ContractError::UnsupportedModule(path).into()), + let query_type = match module.as_str() { + "gamm" => QueryResult::Gamm { + result_type: GammResultTypes::Pool, + }, + "bank" => QueryResult::Bank { + result_type: BankResultTypes::AccountDenomBalance, + }, + _ => return Err(ContractError::UnsupportedModule(module).into()), }; - - let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { - query_type: QueryType::KV.into(), - keys: vec![kv_key], - transactions_filter: String::new(), - connection_id, - update_period, + let query_cfg = PendingQueryIdConfig { + associated_domain_registry: type_registry, + query_type, }; + QUERY_REGISTRATION_REPLY_IDS.save( + deps.storage, + query_registration_resp.reply_id, + &query_cfg, + )?; + // fire registration in a submsg to get the registered query id back - let submsg = SubMsg::reply_on_success(kv_registration_msg, response_code_id); + let submsg = SubMsg::reply_on_success( + query_registration_resp.registration_msg, + query_registration_resp.reply_id, + ); Ok(Response::default().add_submessage(submsg)) } -pub fn update_config( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - new_config: LibraryConfigUpdate, -) -> Result<(), LibraryError> { - new_config.update_config(deps) -} - -pub fn process_function( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: FunctionMsgs, - _cfg: Config, -) -> Result, LibraryError> { - Ok(Response::default()) -} - #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { @@ -177,10 +147,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { resp.push(entry?); } to_json_binary(&resp) - } // QueryMsg::AssertResultCondition { - // query_id, - // condition, - // } => assert_result_condition(deps, query_id, condition), + } } } @@ -206,8 +173,8 @@ fn handle_sudo_kv_query_result( let registered_query_result = get_raw_interchain_query_result(deps.as_ref(), query_id) .map_err(|_| StdError::generic_err("failed to get the raw icq result"))?; - let associated_query_type = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; - let query_result_str = match associated_query_type { + let pending_query_config = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; + let query_result_str = match pending_query_config.query_type { QueryResult::Gamm { result_type } => match result_type { GammResultTypes::Pool => { let any_msg: osmosis_std::shim::Any = osmosis_std::shim::Any::decode( @@ -243,12 +210,7 @@ fn handle_sudo_kv_query_result( #[cfg_attr(not(feature = "library"), entry_point)] pub fn reply(deps: DepsMut, _: Env, msg: Reply) -> StdResult { - match msg.id { - GAMM_QUERY_REGISTRATION_REPLY_ID | BANK_QUERY_REGISTRATION_REPLY_ID => { - try_associate_registered_query_id(deps, msg) - } - _ => Err(ContractError::UnknownReplyId(msg.id).into()), - } + try_associate_registered_query_id(deps, msg) } fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult { @@ -271,16 +233,11 @@ fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult QueryResult::Gamm { - result_type: GammResultTypes::Pool, - }, - BANK_QUERY_REGISTRATION_REPLY_ID => QueryResult::Bank { - result_type: BankResultTypes::AccountDenomBalance, - }, - _ => return Err(ContractError::UnknownReplyId(reply.id).into()), - }; - ASSOCIATED_QUERY_IDS.save(deps.storage, resp.id, &val_type)?; + let query_cfg = QUERY_REGISTRATION_REPLY_IDS.load(deps.storage, reply.id)?; + + ASSOCIATED_QUERY_IDS.save(deps.storage, resp.id, &query_cfg)?; + + QUERY_REGISTRATION_REPLY_IDS.remove(deps.storage, reply.id); Ok(Response::default()) } diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index 258369ef..7c70973a 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -28,11 +28,11 @@ pub struct InstantiateMsg {} #[cw_serde] pub enum FunctionMsgs { RegisterKvQuery { - connection_id: String, - update_period: u64, - // TODO: enum module: String, - // + // address of the target domain type registry contract + type_registry: String, + // json string of the query + query: String, }, } @@ -49,13 +49,6 @@ pub enum QueryMsg { #[returns(Vec<(u64, Value)>)] QueryResults {}, - // #[returns(bool)] - // AssertResultCondition { - // query_id: u64, - // path: String, - // operator: String, - // assertion_value: String, - // }, } #[cw_serde] diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index b48b4fc3..e83abe30 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -1,8 +1,17 @@ use crate::msg::QueryResult; +use cosmwasm_schema::cw_serde; use cw_storage_plus::Map; use serde_json::Value; pub const LOGS: Map = Map::new("logs"); -pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); - +pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); pub const QUERY_RESULTS: Map = Map::new("query_results"); + +pub const QUERY_REGISTRATION_REPLY_IDS: Map = + Map::new("query_registration_reply_ids"); + +#[cw_serde] +pub struct PendingQueryIdConfig { + pub associated_domain_registry: String, + pub query_type: QueryResult, +} diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index 086dd487..094048e7 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -231,11 +231,8 @@ pub fn register_kv_query( #[cfg(test)] mod test { - use cosmwasm_std::{from_json, to_json_string, Binary, Uint128}; - use neutron_sdk::{ - bindings::types::StorageValue, - interchain_queries::{query_kv_result, types::KVReconstruct}, - }; + use cosmwasm_std::{to_json_string, Binary}; + use neutron_sdk::{bindings::types::StorageValue, interchain_queries::types::KVReconstruct}; use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; use prost::Message; use serde_json::Value; @@ -282,7 +279,7 @@ mod test { }; let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(&vec![storage_value]).unwrap(); + KVReconstruct::reconstruct(&[storage_value]).unwrap(); println!("balances: {:?}", balances); } diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index a061cdee..17dcc6a3 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -48,3 +48,5 @@ osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } valence-icq-querier = { workspace = true } +valence-osmosis-type-registry = { workspace = true } +valence-icq-lib-utils = { workspace = true } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index aa3f0baf..d2d32bcc 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -67,6 +67,10 @@ fn main() -> Result<(), Box> { "{}/artifacts/valence_icq_querier.wasm", current_dir.display() ); + let osmo_domain_registry_local_path = format!( + "{}/artifacts/valence_osmosis_type_registry.wasm", + current_dir.display() + ); info!("sleeping to allow icq relayer to start..."); std::thread::sleep(Duration::from_secs(10)); @@ -75,6 +79,10 @@ fn main() -> Result<(), Box> { .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&icq_lib_local_path)?; + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&osmo_domain_registry_local_path)?; + let icq_querier_lib_code_id = test_ctx .get_contract() .contract("valence_icq_querier") @@ -84,6 +92,37 @@ fn main() -> Result<(), Box> { info!("icq querier library code id: {icq_querier_lib_code_id}"); + let osmo_domain_registry_code_id = test_ctx + .get_contract() + .contract("valence_osmosis_type_registry") + .get_cw() + .code_id + .unwrap(); + + let ntrn_to_osmo_connection_id = test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let osmo_domain_registry = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + osmo_domain_registry_code_id, + &serde_json::to_string(&valence_icq_lib_utils::InstantiateMsg { + connection_id: ntrn_to_osmo_connection_id, + })?, + "icq_querier_lib", + None, + "", + )?; + info!( + "osmo_domain_registry address: {}", + osmo_domain_registry.address + ); + // instantiate icq querier lib let icq_test_lib = contract_instantiate( test_ctx @@ -104,8 +143,9 @@ fn main() -> Result<(), Box> { let kvq_registration_response = register_kvq( &test_ctx, icq_test_lib.address.to_string(), - OSMOSIS_CHAIN_NAME.to_string(), + osmo_domain_registry.address.to_string(), "gamm".to_string(), + "query".to_string(), )?; info!( @@ -118,8 +158,9 @@ fn main() -> Result<(), Box> { let kvq_registration_response = register_kvq( &test_ctx, icq_test_lib.address.to_string(), - OSMOSIS_CHAIN_NAME.to_string(), + osmo_domain_registry.address.to_string(), "bank".to_string(), + "query".to_string(), )?; info!( @@ -141,19 +182,16 @@ fn main() -> Result<(), Box> { pub fn register_kvq( test_ctx: &TestContext, icq_lib: String, - domain: String, + type_registry: String, module: String, + query: String, ) -> Result { - info!("registering ICQ KV query on domain {domain} for mod {module}..."); + info!("registering ICQ KV query via type registry {type_registry}..."); let register_kvq_msg = FunctionMsgs::RegisterKvQuery { - connection_id: test_ctx - .get_connections() - .src(NEUTRON_CHAIN_NAME) - .dest(&domain) - .get(), - update_period: 5, + type_registry, module, + query, }; contract_execute( diff --git a/packages/icq-querier-utils/Cargo.toml b/packages/icq-querier-utils/Cargo.toml new file mode 100644 index 00000000..27877fb6 --- /dev/null +++ b/packages/icq-querier-utils/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "valence-icq-lib-utils" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +version = { workspace = true } +repository = { workspace = true } + +[features] +default = [] +testing = [ + "dep:cw-multi-test", + "dep:cw20", + "dep:cw20-base", + "dep:sha2", + "dep:valence-base-account", +] + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-denom = { workspace = true } +cw-ownable = { workspace = true } +cw-utils = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +valence-account-utils = { workspace = true } +valence-macros = { workspace = true } +cw-storage-plus = { workspace = true } +neutron-sdk = { workspace = true } + +# Testing dependencies +cw-multi-test = { workspace = true, optional = true } +cw20 = { workspace = true, optional = true } +cw20-base = { workspace = true, optional = true } +sha2 = { workspace = true, optional = true } +valence-base-account = { workspace = true, optional = true } diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs new file mode 100644 index 00000000..977b6e8f --- /dev/null +++ b/packages/icq-querier-utils/src/lib.rs @@ -0,0 +1,30 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use neutron_sdk::bindings::msg::NeutronMsg; + +#[cw_serde] +pub struct InstantiateMsg { + // connection id of associated chain + pub connection_id: String, +} + +#[cw_serde] +pub enum ExecuteMsg {} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(QueryRegistrationInfoResponse)] + GetRegistrationConfig(QueryRegistrationInfoRequest), +} + +#[cw_serde] +pub struct QueryRegistrationInfoRequest { + pub module: String, + pub query: String, +} + +#[cw_serde] +pub struct QueryRegistrationInfoResponse { + pub registration_msg: NeutronMsg, + pub reply_id: u64, +} From 4afddb5ca68a232cb97ff1505249af8f623e2211 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 29 Nov 2024 16:26:34 +0100 Subject: [PATCH 55/92] cleanup imports --- Cargo.lock | 6 -- .../osmo_registry/src/contract.rs | 53 +++++++++++- .../osmo_registry/src/msg.rs | 16 ---- contracts/libraries/icq-querier/Cargo.toml | 7 -- .../libraries/icq-querier/src/contract.rs | 80 +++++-------------- contracts/libraries/icq-querier/src/msg.rs | 16 ---- contracts/libraries/icq-querier/src/state.rs | 12 +-- packages/icq-querier-utils/src/lib.rs | 40 +++++++++- 8 files changed, 112 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10286f6f..259d3760 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5248,20 +5248,14 @@ dependencies = [ "cw-storage-plus 2.0.0", "cw20 2.0.0", "neutron-sdk", - "osmosis-std", - "osmosis-test-tube", - "prost 0.13.3", - "prost-types 0.13.3", "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", - "valence-account-utils", "valence-icq-lib-utils", "valence-library-base", "valence-library-utils", "valence-macros", "valence-osmosis-type-registry", - "valence-osmosis-utils", ] [[package]] diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index 3c3f318f..73152cc0 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -1,14 +1,20 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{to_json_string, StdError}; use neutron_sdk::bindings::msg::NeutronMsg; use neutron_sdk::bindings::types::KVKey; use neutron_sdk::interchain_queries::helpers::decode_and_convert; -use neutron_sdk::interchain_queries::types::QueryType; +use neutron_sdk::interchain_queries::types::{KVReconstruct, QueryType}; use neutron_sdk::interchain_queries::v047::helpers::create_account_denom_balance_key; use neutron_sdk::interchain_queries::v047::types::BANK_STORE_KEY; +use prost::Message; +use valence_icq_lib_utils::GammResultTypes; +use valence_icq_lib_utils::QueryReconstructionRequest; use valence_icq_lib_utils::QueryRegistrationInfoRequest; use valence_icq_lib_utils::QueryRegistrationInfoResponse; +use valence_icq_lib_utils::QueryResult; +use valence_icq_lib_utils::{BankResultTypes, QueryReconstructionResponse}; use crate::error::ContractError; use crate::state::CONNECTION_ID; @@ -52,11 +58,47 @@ pub fn query(deps: Deps, _env: Env, msg: DomainRegistryQueryMsg) -> StdResult { get_registration_config(deps, request) } + DomainRegistryQueryMsg::ReconstructQuery(query_reconstruction_request) => { + reconstruct_icq_result(query_reconstruction_request) + } } } +fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult { + let query_result_str = match query.query_type { + QueryResult::Gamm { result_type } => match result_type { + GammResultTypes::Pool => { + let any_msg: osmosis_std::shim::Any = + osmosis_std::shim::Any::decode(query.icq_result.kv_results[0].value.as_slice()) + .unwrap(); + assert_eq!(any_msg.type_url, "/osmosis.gamm.v1beta1.Pool"); + + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = + any_msg.try_into().unwrap(); + + to_json_string(&osmo_pool)? + } + }, + QueryResult::Bank { result_type } => match result_type { + BankResultTypes::AccountDenomBalance => { + let balances: neutron_sdk::interchain_queries::v047::types::Balances = + KVReconstruct::reconstruct(&query.icq_result.kv_results).unwrap(); + + to_json_string(&balances)? + } + }, + }; + + let resp = QueryReconstructionResponse { + json_value: serde_json::from_str(&query_result_str) + .map_err(|_| StdError::generic_err("failed to get json value".to_string()))?, + }; + + to_json_binary(&resp) +} + fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> StdResult { - let (kv_key, response_code_id) = match query.module.as_str() { + let (kv_key, response_code_id, query_type) = match query.module.as_str() { "gamm" => { let pool_prefix_key: u8 = 0x02; let pool_id: u64 = 1; @@ -69,6 +111,9 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S key: Binary::new(pool_access_key), }, GAMM_QUERY_REGISTRATION_REPLY_ID, + QueryResult::Gamm { + result_type: GammResultTypes::Pool, + }, ) } "bank" => { @@ -83,6 +128,9 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S key: Binary::new(balance_key), }, BANK_QUERY_REGISTRATION_REPLY_ID, + QueryResult::Bank { + result_type: BankResultTypes::AccountDenomBalance, + }, ) } _ => return Err(ContractError::UnsupportedModule(query.module).into()), @@ -101,6 +149,7 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S let query = QueryRegistrationInfoResponse { registration_msg: kv_registration_msg, reply_id: response_code_id, + query_type, }; to_json_binary(&query) diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index 3df6ece6..8b137891 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -1,17 +1 @@ -use cosmwasm_schema::cw_serde; -#[cw_serde] -pub enum QueryResult { - Gamm { result_type: GammResultTypes }, - Bank { result_type: BankResultTypes }, -} - -#[cw_serde] -pub enum GammResultTypes { - Pool, -} - -#[cw_serde] -pub enum BankResultTypes { - AccountDenomBalance, -} diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 9640b325..415f8b9d 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -20,11 +20,6 @@ cw-ownable = { workspace = true } valence-macros = { workspace = true } valence-library-utils = { workspace = true } valence-library-base = { workspace = true } -osmosis-std = { workspace = true } -valence-account-utils = { workspace = true } -valence-osmosis-utils = { workspace = true } -prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } -prost-types = { version = "0.13.3", default-features = false } neutron-sdk = { workspace = true } serde-json-wasm = { version = "1.0.0", default-features = false } cw-storage-plus = { workspace = true } @@ -35,5 +30,3 @@ valence-icq-lib-utils = { workspace = true } [dev-dependencies] cw20 = { workspace = true } -osmosis-test-tube = { workspace = true } -valence-osmosis-utils = { workspace = true, features = ["testing"] } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index e6e1b923..f7434991 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -9,26 +9,19 @@ use neutron_sdk::{ msg::{MsgRegisterInterchainQueryResponse, NeutronMsg}, query::NeutronQuery, }, - interchain_queries::{queries::get_raw_interchain_query_result, types::KVReconstruct}, + interchain_queries::queries::get_raw_interchain_query_result, sudo::msg::SudoMsg, }; -use prost::Message; -use valence_icq_lib_utils::QueryMsg as DomainRegistryQueryMsg; +use serde_json::Value; use valence_icq_lib_utils::QueryRegistrationInfoRequest as DomainRegistryQueryRequest; +use valence_icq_lib_utils::{PendingQueryIdConfig, QueryMsg as DomainRegistryQueryMsg}; use valence_icq_lib_utils::QueryRegistrationInfoResponse; use valence_library_utils::error::LibraryError; use crate::{ - error::ContractError, - msg::{ - BankResultTypes, Config, FunctionMsgs, GammResultTypes, InstantiateMsg, LibraryConfig, - QueryMsg, QueryResult, - }, - state::{ - PendingQueryIdConfig, ASSOCIATED_QUERY_IDS, LOGS, QUERY_REGISTRATION_REPLY_IDS, - QUERY_RESULTS, - }, + msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, QueryMsg}, + state::{ASSOCIATED_QUERY_IDS, LOGS, QUERY_RESULTS}, }; // version info for migration info @@ -80,25 +73,14 @@ fn register_kv_query( }), )?; - let query_type = match module.as_str() { - "gamm" => QueryResult::Gamm { - result_type: GammResultTypes::Pool, - }, - "bank" => QueryResult::Bank { - result_type: BankResultTypes::AccountDenomBalance, - }, - _ => return Err(ContractError::UnsupportedModule(module).into()), - }; let query_cfg = PendingQueryIdConfig { associated_domain_registry: type_registry, - query_type, + query_type: query_registration_resp.query_type, }; - QUERY_REGISTRATION_REPLY_IDS.save( - deps.storage, - query_registration_resp.reply_id, - &query_cfg, - )?; + // here the key is set to the resp.reply_id just to get to the reply handler. + // it will get overriden by the actual query id in the reply handler. + ASSOCIATED_QUERY_IDS.save(deps.storage, query_registration_resp.reply_id, &query_cfg)?; // fire registration in a submsg to get the registered query id back let submsg = SubMsg::reply_on_success( @@ -174,34 +156,16 @@ fn handle_sudo_kv_query_result( .map_err(|_| StdError::generic_err("failed to get the raw icq result"))?; let pending_query_config = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; - let query_result_str = match pending_query_config.query_type { - QueryResult::Gamm { result_type } => match result_type { - GammResultTypes::Pool => { - let any_msg: osmosis_std::shim::Any = osmosis_std::shim::Any::decode( - registered_query_result.result.kv_results[0] - .value - .as_slice(), - ) - .unwrap(); - assert_eq!(any_msg.type_url, "/osmosis.gamm.v1beta1.Pool"); - - let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = - any_msg.try_into().unwrap(); - - to_json_string(&osmo_pool).unwrap() - } - }, - QueryResult::Bank { result_type } => match result_type { - BankResultTypes::AccountDenomBalance => { - let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(®istered_query_result.result.kv_results).unwrap(); - to_json_string(&balances).unwrap() - } - }, - }; - - let json_response: serde_json::Value = serde_json::from_str(&query_result_str).unwrap(); + let json_response: Value = deps.querier.query_wasm_smart( + pending_query_config.associated_domain_registry, + &DomainRegistryQueryMsg::ReconstructQuery( + valence_icq_lib_utils::QueryReconstructionRequest { + icq_result: registered_query_result.result, + query_type: pending_query_config.query_type, + }, + ), + )?; QUERY_RESULTS.save(deps.storage, query_id, &json_response)?; @@ -233,11 +197,9 @@ fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult = Map::new("logs"); pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); pub const QUERY_RESULTS: Map = Map::new("query_results"); - -pub const QUERY_REGISTRATION_REPLY_IDS: Map = - Map::new("query_registration_reply_ids"); - -#[cw_serde] -pub struct PendingQueryIdConfig { - pub associated_domain_registry: String, - pub query_type: QueryResult, -} diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs index 977b6e8f..c1e42b0d 100644 --- a/packages/icq-querier-utils/src/lib.rs +++ b/packages/icq-querier-utils/src/lib.rs @@ -1,5 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use neutron_sdk::bindings::msg::NeutronMsg; +use neutron_sdk::bindings::{msg::NeutronMsg, types::InterchainQueryResult}; +use serde_json::Value; #[cw_serde] pub struct InstantiateMsg { @@ -15,6 +16,20 @@ pub enum ExecuteMsg {} pub enum QueryMsg { #[returns(QueryRegistrationInfoResponse)] GetRegistrationConfig(QueryRegistrationInfoRequest), + + #[returns(QueryReconstructionResponse)] + ReconstructQuery(QueryReconstructionRequest), +} + +#[cw_serde] +pub struct QueryReconstructionRequest { + pub icq_result: InterchainQueryResult, + pub query_type: QueryResult, +} + +#[cw_serde] +pub struct QueryReconstructionResponse { + pub json_value: Value, } #[cw_serde] @@ -27,4 +42,27 @@ pub struct QueryRegistrationInfoRequest { pub struct QueryRegistrationInfoResponse { pub registration_msg: NeutronMsg, pub reply_id: u64, + pub query_type: QueryResult, +} + +#[cw_serde] +pub enum QueryResult { + Gamm { result_type: GammResultTypes }, + Bank { result_type: BankResultTypes }, +} + +#[cw_serde] +pub enum GammResultTypes { + Pool, +} + +#[cw_serde] +pub enum BankResultTypes { + AccountDenomBalance, +} + +#[cw_serde] +pub struct PendingQueryIdConfig { + pub associated_domain_registry: String, + pub query_type: QueryResult, } From e2b7b932dd33a8c801b6034dfc17bb6b98efc308 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 29 Nov 2024 18:21:37 +0100 Subject: [PATCH 56/92] init macro for osmo types parser --- .../osmo_registry/src/msg.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index 8b137891..b76de89f 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -1 +1,37 @@ +use std::str::FromStr; +use cosmwasm_schema::cw_serde; + +use crate::error::ContractError; + +macro_rules! define_osmosis_types { + ($(($variant:ident, $type:ty)),* $(,)?) => { + #[allow(clippy::large_enum_variant)] + #[cw_serde] + pub enum OsmosisTypes { + $( + $variant($type), + )* + } + + impl FromStr for OsmosisTypes { + type Err = ContractError; + + fn from_str(type_url: &str) -> Result { + match type_url { + $( + <$type>::TYPE_URL => Ok(OsmosisTypes::$variant(<$type>::default())), + )* + _ => Err(ContractError::UnknownTypeUrl(type_url.to_string())), + } + } + } + }; +} + +define_osmosis_types! { + (GammV1Beta1Pool, osmosis_std::types::osmosis::gamm::v1beta1::Pool), + (GammV1Beta1ParamsResponse, osmosis_std::types::osmosis::gamm::v1beta1::ParamsResponse), + (GammV1Beta1QueryCalcExitPoolCoinsFromSharesRequest, osmosis_std::types::osmosis::gamm::v1beta1::QueryCalcExitPoolCoinsFromSharesRequest), + (BankV1Beta1BalanceResponse, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) +} From 8cd9047a8d165bfccb8b7b4291fb24b3f62a6d67 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 29 Nov 2024 23:06:55 +0100 Subject: [PATCH 57/92] cleanup icq-querier & e2e test --- .../osmo_registry/src/contract.rs | 30 +++++++----- .../osmo_registry/src/error.rs | 3 ++ .../libraries/icq-querier/src/contract.rs | 48 +++++++------------ contracts/libraries/icq-querier/src/msg.rs | 3 -- contracts/libraries/icq-querier/src/state.rs | 1 - contracts/testing/test-icq-lib/src/icq.rs | 27 ++++++++++- .../examples/interchain_querier.rs | 42 ++++++---------- 7 files changed, 76 insertions(+), 78 deletions(-) diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index 73152cc0..47175131 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; @@ -8,7 +10,9 @@ use neutron_sdk::interchain_queries::helpers::decode_and_convert; use neutron_sdk::interchain_queries::types::{KVReconstruct, QueryType}; use neutron_sdk::interchain_queries::v047::helpers::create_account_denom_balance_key; use neutron_sdk::interchain_queries::v047::types::BANK_STORE_KEY; +use osmosis_std::shim::Any; use prost::Message; +use serde_json::Value; use valence_icq_lib_utils::GammResultTypes; use valence_icq_lib_utils::QueryReconstructionRequest; use valence_icq_lib_utils::QueryRegistrationInfoRequest; @@ -17,6 +21,7 @@ use valence_icq_lib_utils::QueryResult; use valence_icq_lib_utils::{BankResultTypes, QueryReconstructionResponse}; use crate::error::ContractError; +use crate::msg::OsmosisTypes; use crate::state::CONNECTION_ID; use valence_icq_lib_utils::ExecuteMsg as DomainRegistryExecuteMsg; @@ -68,10 +73,8 @@ fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult match result_type { GammResultTypes::Pool => { - let any_msg: osmosis_std::shim::Any = - osmosis_std::shim::Any::decode(query.icq_result.kv_results[0].value.as_slice()) - .unwrap(); - assert_eq!(any_msg.type_url, "/osmosis.gamm.v1beta1.Pool"); + let any_msg: Any = Any::decode(query.icq_result.kv_results[0].value.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = any_msg.try_into().unwrap(); @@ -89,17 +92,18 @@ fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult StdResult { - let (kv_key, response_code_id, query_type) = match query.module.as_str() { - "gamm" => { + let osmo_type = OsmosisTypes::from_str(&query.module)?; + + let (kv_key, response_code_id, query_type) = match osmo_type { + OsmosisTypes::GammV1Beta1Pool(_pool) => { let pool_prefix_key: u8 = 0x02; let pool_id: u64 = 1; let mut pool_access_key = vec![pool_prefix_key]; @@ -107,7 +111,7 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S ( KVKey { - path: query.module.to_string(), + path: "gamm".to_string(), key: Binary::new(pool_access_key), }, GAMM_QUERY_REGISTRATION_REPLY_ID, @@ -116,7 +120,7 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S }, ) } - "bank" => { + OsmosisTypes::BankV1Beta1BalanceResponse(_query_balance_response) => { let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63".to_string(); let converted_addr_bytes = decode_and_convert(&addr).unwrap(); let balance_key = @@ -133,7 +137,7 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S }, ) } - _ => return Err(ContractError::UnsupportedModule(query.module).into()), + _ => unimplemented!(), }; let connection_id = CONNECTION_ID.load(deps.storage)?; diff --git a/contracts/domain_type_registries/osmo_registry/src/error.rs b/contracts/domain_type_registries/osmo_registry/src/error.rs index 51835b73..7d49dc34 100644 --- a/contracts/domain_type_registries/osmo_registry/src/error.rs +++ b/contracts/domain_type_registries/osmo_registry/src/error.rs @@ -11,6 +11,9 @@ pub enum ContractError { #[error("Unsupported module: {0}")] UnsupportedModule(String), + + #[error("Unknown type URL: {0}")] + UnknownTypeUrl(String), } impl From for StdError { diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index f7434991..0ec715b4 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -12,16 +12,17 @@ use neutron_sdk::{ interchain_queries::queries::get_raw_interchain_query_result, sudo::msg::SudoMsg, }; -use serde_json::Value; -use valence_icq_lib_utils::QueryRegistrationInfoRequest as DomainRegistryQueryRequest; use valence_icq_lib_utils::{PendingQueryIdConfig, QueryMsg as DomainRegistryQueryMsg}; +use valence_icq_lib_utils::{ + QueryReconstructionResponse, QueryRegistrationInfoRequest as DomainRegistryQueryRequest, +}; use valence_icq_lib_utils::QueryRegistrationInfoResponse; use valence_library_utils::error::LibraryError; use crate::{ msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, QueryMsg}, - state::{ASSOCIATED_QUERY_IDS, LOGS, QUERY_RESULTS}, + state::{ASSOCIATED_QUERY_IDS, QUERY_RESULTS}, }; // version info for migration info @@ -68,14 +69,14 @@ fn register_kv_query( let query_registration_resp: QueryRegistrationInfoResponse = deps.querier.query_wasm_smart( type_registry.to_string(), &DomainRegistryQueryMsg::GetRegistrationConfig(DomainRegistryQueryRequest { - module: module.to_string(), + module, query, }), )?; let query_cfg = PendingQueryIdConfig { associated_domain_registry: type_registry, - query_type: query_registration_resp.query_type, + query_type: query_registration_resp.query_type.clone(), }; // here the key is set to the resp.reply_id just to get to the reply handler. @@ -84,11 +85,14 @@ fn register_kv_query( // fire registration in a submsg to get the registered query id back let submsg = SubMsg::reply_on_success( - query_registration_resp.registration_msg, + query_registration_resp.registration_msg.clone(), query_registration_resp.reply_id, ); - Ok(Response::default().add_submessage(submsg)) + Ok(Response::default().add_submessage(submsg).add_attribute( + "query_registration_response".to_string(), + to_json_string(&query_registration_resp)?, + )) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -116,13 +120,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } to_json_binary(&resp) } - QueryMsg::Logs {} => { - let mut resp = vec![]; - for entry in LOGS.range(deps.storage, None, None, Order::Ascending) { - resp.push(entry?); - } - to_json_binary(&resp) - } QueryMsg::QueryResults {} => { let mut resp = vec![]; for entry in QUERY_RESULTS.range(deps.storage, None, None, Order::Ascending) { @@ -134,17 +131,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo(deps: ExecuteDeps, env: Env, msg: SudoMsg) -> StdResult> { +pub fn sudo(deps: ExecuteDeps, _env: Env, msg: SudoMsg) -> StdResult> { match msg { SudoMsg::KVQueryResult { query_id } => handle_sudo_kv_query_result(deps, query_id), - _ => { - LOGS.save( - deps.storage, - format!("sudo_catchall_handler-{}", env.block.height).to_string(), - &to_json_string(&msg)?, - )?; - Ok(Response::default()) - } + _ => Ok(Response::default()), } } @@ -157,7 +147,7 @@ fn handle_sudo_kv_query_result( let pending_query_config = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; - let json_response: Value = deps.querier.query_wasm_smart( + let json_response: QueryReconstructionResponse = deps.querier.query_wasm_smart( pending_query_config.associated_domain_registry, &DomainRegistryQueryMsg::ReconstructQuery( valence_icq_lib_utils::QueryReconstructionRequest { @@ -167,9 +157,9 @@ fn handle_sudo_kv_query_result( ), )?; - QUERY_RESULTS.save(deps.storage, query_id, &json_response)?; + QUERY_RESULTS.save(deps.storage, query_id, &json_response.json_value)?; - Ok(Response::new().add_attribute("query_result", json_response.to_string())) + Ok(Response::new().add_attribute("query_result", json_response.json_value.to_string())) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -191,12 +181,6 @@ fn try_associate_registered_query_id(deps: DepsMut, reply: Reply) -> StdResult)] - Logs {}, - #[returns(Vec<(u64, String)>)] RegisteredQueries {}, diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index 617fb8b8..f2ebbee5 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -2,6 +2,5 @@ use cw_storage_plus::Map; use serde_json::Value; use valence_icq_lib_utils::PendingQueryIdConfig; -pub const LOGS: Map = Map::new("logs"); pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); pub const QUERY_RESULTS: Map = Map::new("query_results"); diff --git a/contracts/testing/test-icq-lib/src/icq.rs b/contracts/testing/test-icq-lib/src/icq.rs index 094048e7..931bb96d 100644 --- a/contracts/testing/test-icq-lib/src/icq.rs +++ b/contracts/testing/test-icq-lib/src/icq.rs @@ -232,7 +232,12 @@ pub fn register_kv_query( #[cfg(test)] mod test { use cosmwasm_std::{to_json_string, Binary}; - use neutron_sdk::{bindings::types::StorageValue, interchain_queries::types::KVReconstruct}; + use neutron_sdk::{ + bindings::types::StorageValue, + interchain_queries::{ + types::KVReconstruct, v047::helpers::deconstruct_account_denom_balance_key, + }, + }; use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; use prost::Message; use serde_json::Value; @@ -283,4 +288,24 @@ mod test { println!("balances: {:?}", balances); } + + #[test] + fn try_decode_balance_response_from_binary_alt() { + let b64_key = "AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "OTk4Nzg5OTk3MjUwMA=="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "bank".to_string(), + key: binary_key, + value: binary_value, + }; + + let (_, denom) = deconstruct_account_denom_balance_key(storage_value.key.to_vec()).unwrap(); + println!("denom: {denom}"); + let value_str = String::from_utf8(storage_value.value.to_vec()).unwrap(); + println!("value_str: {value_str}"); + } } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index d2d32bcc..7e418a33 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -144,7 +144,7 @@ fn main() -> Result<(), Box> { &test_ctx, icq_test_lib.address.to_string(), osmo_domain_registry.address.to_string(), - "gamm".to_string(), + "/osmosis.gamm.v1beta1.Pool".to_string(), "query".to_string(), )?; @@ -153,13 +153,13 @@ fn main() -> Result<(), Box> { kvq_registration_response ); - std::thread::sleep(Duration::from_secs(5)); + std::thread::sleep(Duration::from_secs(2)); let kvq_registration_response = register_kvq( &test_ctx, icq_test_lib.address.to_string(), osmo_domain_registry.address.to_string(), - "bank".to_string(), + "/cosmos.bank.v1beta1.QueryBalanceResponse".to_string(), "query".to_string(), )?; @@ -168,13 +168,18 @@ fn main() -> Result<(), Box> { kvq_registration_response ); - std::thread::sleep(Duration::from_secs(5)); + let mut results_found = false; + while !results_found { + let results = query_results(&test_ctx, icq_test_lib.address.to_string())?; - let logs = query_logs(&test_ctx, icq_test_lib.address.to_string())?; - info!("logs: {:?}", logs); - - let results = query_results(&test_ctx, icq_test_lib.address.to_string())?; - info!("results: {:?}", results); + if !results.is_empty() { + info!("results: {:?}", results); + results_found = true; + } else { + info!("no results yet; sleeping for 3..."); + std::thread::sleep(Duration::from_secs(3)); + } + } Ok(()) } @@ -206,25 +211,6 @@ pub fn register_kvq( ) } -pub fn query_logs( - test_ctx: &TestContext, - icq_lib: String, -) -> Result, LocalError> { - let query_response = contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - &serde_json::to_string(&QueryMsg::Logs {}) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - )["data"] - .clone(); - - let resp: Vec<(String, String)> = serde_json::from_value(query_response).unwrap(); - - Ok(resp) -} - pub fn query_results( test_ctx: &TestContext, icq_lib: String, From 8087f826748b8208ca212a5bd3cfdec5693bac5a Mon Sep 17 00:00:00 2001 From: bekauz Date: Sat, 30 Nov 2024 19:29:13 +0100 Subject: [PATCH 58/92] declaring pool & balance query over macro impl; cleanup get_registration_config query structure --- .../osmo_registry/src/contract.rs | 45 +---- .../osmo_registry/src/msg.rs | 188 +++++++++++++++++- .../osmo_registry/src/state.rs | 1 + .../libraries/icq-querier/src/contract.rs | 7 +- contracts/libraries/icq-querier/src/msg.rs | 2 +- .../examples/interchain_querier.rs | 44 ++-- packages/icq-querier-utils/src/lib.rs | 2 +- 7 files changed, 222 insertions(+), 67 deletions(-) diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index 47175131..3d4b0aed 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -5,11 +5,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use cosmwasm_std::{to_json_string, StdError}; use neutron_sdk::bindings::msg::NeutronMsg; -use neutron_sdk::bindings::types::KVKey; -use neutron_sdk::interchain_queries::helpers::decode_and_convert; use neutron_sdk::interchain_queries::types::{KVReconstruct, QueryType}; -use neutron_sdk::interchain_queries::v047::helpers::create_account_denom_balance_key; -use neutron_sdk::interchain_queries::v047::types::BANK_STORE_KEY; use osmosis_std::shim::Any; use prost::Message; use serde_json::Value; @@ -32,9 +28,6 @@ use valence_icq_lib_utils::QueryMsg as DomainRegistryQueryMsg; const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -const GAMM_QUERY_REGISTRATION_REPLY_ID: u64 = 31415; -const BANK_QUERY_REGISTRATION_REPLY_ID: u64 = 31416; - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -102,43 +95,7 @@ fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult StdResult { let osmo_type = OsmosisTypes::from_str(&query.module)?; - let (kv_key, response_code_id, query_type) = match osmo_type { - OsmosisTypes::GammV1Beta1Pool(_pool) => { - let pool_prefix_key: u8 = 0x02; - let pool_id: u64 = 1; - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); - - ( - KVKey { - path: "gamm".to_string(), - key: Binary::new(pool_access_key), - }, - GAMM_QUERY_REGISTRATION_REPLY_ID, - QueryResult::Gamm { - result_type: GammResultTypes::Pool, - }, - ) - } - OsmosisTypes::BankV1Beta1BalanceResponse(_query_balance_response) => { - let addr = "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63".to_string(); - let converted_addr_bytes = decode_and_convert(&addr).unwrap(); - let balance_key = - create_account_denom_balance_key(converted_addr_bytes, "uosmo").unwrap(); - - ( - KVKey { - path: BANK_STORE_KEY.to_string(), - key: Binary::new(balance_key), - }, - BANK_QUERY_REGISTRATION_REPLY_ID, - QueryResult::Bank { - result_type: BankResultTypes::AccountDenomBalance, - }, - ) - } - _ => unimplemented!(), - }; + let (kv_key, response_code_id, query_type) = osmo_type.get_registration_config(query.params)?; let connection_id = CONNECTION_ID.load(deps.storage)?; diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index b76de89f..f0e74140 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -1,9 +1,26 @@ use std::str::FromStr; use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Binary, StdError, StdResult}; +use neutron_sdk::{ + bindings::types::KVKey, + interchain_queries::{ + helpers::decode_and_convert, + v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, + }, +}; +use serde_json::Value; +use valence_icq_lib_utils::{BankResultTypes, GammResultTypes, QueryResult}; use crate::error::ContractError; +pub trait QueryTypeDefinition { + const REPLY_ID: u64; + + fn get_query_type(&self) -> QueryResult; + fn get_kv_key(&self, params: serde_json::Map) -> StdResult; +} + macro_rules! define_osmosis_types { ($(($variant:ident, $type:ty)),* $(,)?) => { #[allow(clippy::large_enum_variant)] @@ -14,7 +31,9 @@ macro_rules! define_osmosis_types { )* } - impl FromStr for OsmosisTypes { + impl FromStr for OsmosisTypes + where $($type: QueryTypeDefinition),* + { type Err = ContractError; fn from_str(type_url: &str) -> Result { @@ -26,12 +45,173 @@ macro_rules! define_osmosis_types { } } } + + impl OsmosisTypes { + pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64, QueryResult)> { + match self { + $( + OsmosisTypes::$variant(t) => Ok(( + t.get_kv_key(params)?, + <$type>::REPLY_ID, + t.get_query_type() + )), + )* + } + } + } }; } define_osmosis_types! { (GammV1Beta1Pool, osmosis_std::types::osmosis::gamm::v1beta1::Pool), - (GammV1Beta1ParamsResponse, osmosis_std::types::osmosis::gamm::v1beta1::ParamsResponse), - (GammV1Beta1QueryCalcExitPoolCoinsFromSharesRequest, osmosis_std::types::osmosis::gamm::v1beta1::QueryCalcExitPoolCoinsFromSharesRequest), - (BankV1Beta1BalanceResponse, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) + (BankV1Beta1Balance, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) +} + +impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { + const REPLY_ID: u64 = 31415; + + fn get_query_type(&self) -> QueryResult { + QueryResult::Gamm { + result_type: GammResultTypes::Pool, + } + } + + fn get_kv_key(&self, params: serde_json::Map) -> StdResult { + let pool_prefix_key: u8 = 0x02; + let pool_id = match params["pool_id"].clone() { + Value::Number(number) => match number.as_u64() { + Some(n) => n, + None => { + return Err(StdError::generic_err(format!( + "failed to parse {:?} as u64 for pool_id access", + number + ))) + } + }, + Value::String(str_num) => str_num.parse::().map_err(|_| { + StdError::generic_err(format!("failed to parse pool_id {:?} to u64", str_num)) + })?, + _ => { + return Err(StdError::generic_err(format!( + "field pool_id missing from query params: {:?}", + params + ))) + } + }; + + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); + + Ok(KVKey { + path: "gamm".to_string(), + key: Binary::new(pool_access_key), + }) + } +} + +impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse { + const REPLY_ID: u64 = 31416; + + fn get_query_type(&self) -> QueryResult { + QueryResult::Bank { + result_type: BankResultTypes::AccountDenomBalance, + } + } + + fn get_kv_key(&self, params: serde_json::Map) -> StdResult { + // let addr = params["addr"].to_string(); + + let addr = match params["addr"].clone() { + Value::String(address_str) => address_str, + _ => { + return Err(StdError::generic_err(format!( + "field addr missing from query params: {:?}", + params + ))) + } + }; + + let denom = match params["denom"].clone() { + Value::String(denom_str) => denom_str, + _ => { + return Err(StdError::generic_err(format!( + "field denom missing from query params: {:?}", + params + ))) + } + }; + + // let denom = params["denom"].to_string(); + + let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + + let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); + + Ok(KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn test_balance_get_kv_key() { + let balance = osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::default(); + let params = json!({ + "addr": "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63", + "denom": "uosmo" + }); + + let param_map = params.as_object().unwrap(); + + let result = balance.get_kv_key(param_map.clone()).unwrap(); + } + + #[test] + fn test_json_map_serde() { + let params = json!({ + "pool_id": "1" + }); + + let json_restored: serde_json::Map = params.as_object().unwrap().clone(); + println!("json restored: {:?}", json_restored); + + let pool_id = json_restored["pool_id"].as_u64().unwrap(); + + println!("pool_id: {:?}", pool_id); + } + + #[test] + fn test_gamm_pool_get_kv_key() { + let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool::default(); + let params = json!({ + "pool_id": 1 + }); + + let param_str = params.to_string(); + + let json_restored: Value = serde_json::from_str(¶m_str).unwrap(); + println!("json restored: {:?}", json_restored); + + let pool_id = json_restored["pool_id"].as_u64().unwrap(); + + println!("pool_id: {:?}", pool_id); + + let param_map = params.as_object().unwrap(); + + let result = pool.get_kv_key(param_map.clone()).unwrap(); + + assert_eq!(result.path, "gamm"); + let expected_key = { + let mut key = vec![0x02]; + key.extend_from_slice(&1u64.to_be_bytes()); + key + }; + assert_eq!(result.key.as_slice(), expected_key.as_slice()); + } } diff --git a/contracts/domain_type_registries/osmo_registry/src/state.rs b/contracts/domain_type_registries/osmo_registry/src/state.rs index 04982b18..276d052c 100644 --- a/contracts/domain_type_registries/osmo_registry/src/state.rs +++ b/contracts/domain_type_registries/osmo_registry/src/state.rs @@ -1,3 +1,4 @@ use cw_storage_plus::Item; +// connection id from home domain to osmosis pub const CONNECTION_ID: Item = Item::new("connection_id"); diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 0ec715b4..0c1b3f81 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -12,6 +12,7 @@ use neutron_sdk::{ interchain_queries::queries::get_raw_interchain_query_result, sudo::msg::SudoMsg, }; +use serde_json::Value; use valence_icq_lib_utils::{PendingQueryIdConfig, QueryMsg as DomainRegistryQueryMsg}; use valence_icq_lib_utils::{ QueryReconstructionResponse, QueryRegistrationInfoRequest as DomainRegistryQueryRequest, @@ -39,7 +40,6 @@ pub fn instantiate( _info: MessageInfo, _msg: InstantiateMsg, ) -> Result, LibraryError> { - // valence_library_base::instantiate(deps, CONTRACT_NAME, CONTRACT_VERSION, msg) Ok(Response::default()) } @@ -50,7 +50,6 @@ pub fn execute( _info: MessageInfo, msg: FunctionMsgs, ) -> Result, LibraryError> { - // valence_library_base::execute(deps, env, info, msg, process_function, update_config) match msg { FunctionMsgs::RegisterKvQuery { type_registry, @@ -64,13 +63,13 @@ fn register_kv_query( deps: DepsMut, type_registry: String, module: String, - query: String, + query: serde_json::Map, ) -> Result, LibraryError> { let query_registration_resp: QueryRegistrationInfoResponse = deps.querier.query_wasm_smart( type_registry.to_string(), &DomainRegistryQueryMsg::GetRegistrationConfig(DomainRegistryQueryRequest { module, - query, + params: query, }), )?; diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index 4a9c1230..4ef57b7a 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -16,7 +16,7 @@ pub enum FunctionMsgs { // address of the target domain type registry contract type_registry: String, // json string of the query - query: String, + query: serde_json::Map, }, } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index 7e418a33..dbe8719a 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -9,14 +9,14 @@ use localic_std::{ types::TransactionResponse, }; use log::info; -use serde_json::Value; +use serde_json::{json, Value}; use std::{env, error::Error, time::Duration}; use valence_icq_querier::msg::{FunctionMsgs, InstantiateMsg, QueryMsg}; use localic_utils::{ utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, - LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, - OSMOSIS_CHAIN_NAME, + LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, + OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_NAME, }; // KeyNextGlobalPoolId defines key to store the next Pool ID to be used. @@ -140,12 +140,18 @@ fn main() -> Result<(), Box> { info!("attempting GAMM total liquidity query"); + let gamm_query_params = json!({ + "pool_id": "1" + }); + + println!("json gamm query: {:?}", gamm_query_params); + let kvq_registration_response = register_kvq( &test_ctx, icq_test_lib.address.to_string(), osmo_domain_registry.address.to_string(), - "/osmosis.gamm.v1beta1.Pool".to_string(), - "query".to_string(), + osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), + gamm_query_params.as_object().unwrap().clone(), )?; info!( @@ -155,12 +161,19 @@ fn main() -> Result<(), Box> { std::thread::sleep(Duration::from_secs(2)); + let bank_query_params = json!({ + "addr": OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + "denom": OSMOSIS_CHAIN_DENOM.to_string(), + }); + + println!("json bank query: {:?}", bank_query_params); + let kvq_registration_response = register_kvq( &test_ctx, icq_test_lib.address.to_string(), osmo_domain_registry.address.to_string(), - "/cosmos.bank.v1beta1.QueryBalanceResponse".to_string(), - "query".to_string(), + osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::TYPE_URL.to_string(), + bank_query_params.as_object().unwrap().clone(), )?; info!( @@ -172,7 +185,7 @@ fn main() -> Result<(), Box> { while !results_found { let results = query_results(&test_ctx, icq_test_lib.address.to_string())?; - if !results.is_empty() { + if results.len() == 2 { info!("results: {:?}", results); results_found = true; } else { @@ -189,24 +202,29 @@ pub fn register_kvq( icq_lib: String, type_registry: String, module: String, - query: String, + query: serde_json::Map, ) -> Result { - info!("registering ICQ KV query via type registry {type_registry}..."); - let register_kvq_msg = FunctionMsgs::RegisterKvQuery { type_registry, module, query, }; + let stringified_msg = serde_json::to_string(®ister_kvq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + + info!( + "registering ICQ KV query on querier {icq_lib} : {:?}", + stringified_msg + ); + contract_execute( test_ctx .get_request_builder() .get_request_builder(NEUTRON_CHAIN_NAME), &icq_lib, DEFAULT_KEY, - &serde_json::to_string(®ister_kvq_msg) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + &stringified_msg, "--amount 1000000untrn --gas 50000000", ) } diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs index c1e42b0d..bdc3c17b 100644 --- a/packages/icq-querier-utils/src/lib.rs +++ b/packages/icq-querier-utils/src/lib.rs @@ -35,7 +35,7 @@ pub struct QueryReconstructionResponse { #[cw_serde] pub struct QueryRegistrationInfoRequest { pub module: String, - pub query: String, + pub params: serde_json::Map, } #[cw_serde] From 6f28d268108c6283d81a916d3cb7dc90024ee637 Mon Sep 17 00:00:00 2001 From: bekauz Date: Sun, 1 Dec 2024 16:31:10 +0100 Subject: [PATCH 59/92] remove QueryResult and map directly via type urls; extend type macro with reconstruct_response call for each variant --- .../osmo_registry/src/contract.rs | 41 +++-------- .../osmo_registry/src/msg.rs | 68 ++++++++++++------- .../libraries/icq-querier/src/contract.rs | 4 +- packages/icq-querier-utils/src/lib.rs | 26 ++----- 4 files changed, 61 insertions(+), 78 deletions(-) diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index 3d4b0aed..78116c18 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -3,18 +3,12 @@ use std::str::FromStr; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; -use cosmwasm_std::{to_json_string, StdError}; use neutron_sdk::bindings::msg::NeutronMsg; -use neutron_sdk::interchain_queries::types::{KVReconstruct, QueryType}; -use osmosis_std::shim::Any; -use prost::Message; -use serde_json::Value; -use valence_icq_lib_utils::GammResultTypes; +use neutron_sdk::interchain_queries::types::QueryType; use valence_icq_lib_utils::QueryReconstructionRequest; +use valence_icq_lib_utils::QueryReconstructionResponse; use valence_icq_lib_utils::QueryRegistrationInfoRequest; use valence_icq_lib_utils::QueryRegistrationInfoResponse; -use valence_icq_lib_utils::QueryResult; -use valence_icq_lib_utils::{BankResultTypes, QueryReconstructionResponse}; use crate::error::ContractError; use crate::msg::OsmosisTypes; @@ -63,31 +57,13 @@ pub fn query(deps: Deps, _env: Env, msg: DomainRegistryQueryMsg) -> StdResult StdResult { - let query_result_str = match query.query_type { - QueryResult::Gamm { result_type } => match result_type { - GammResultTypes::Pool => { - let any_msg: Any = Any::decode(query.icq_result.kv_results[0].value.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))?; - - let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = - any_msg.try_into().unwrap(); - - to_json_string(&osmo_pool)? - } - }, - QueryResult::Bank { result_type } => match result_type { - BankResultTypes::AccountDenomBalance => { - let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(&query.icq_result.kv_results).unwrap(); - - to_json_string(&balances)? - } - }, - }; + let underlying_type = OsmosisTypes::from_str(&query.query_type)?; - let json_value: Value = serde_json::from_str(&query_result_str).unwrap(); + let reconstructed_json_value = underlying_type.reconstruct_response(&query)?; - let resp = QueryReconstructionResponse { json_value }; + let resp = QueryReconstructionResponse { + json_value: reconstructed_json_value, + }; to_json_binary(&resp) } @@ -95,7 +71,7 @@ fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult StdResult { let osmo_type = OsmosisTypes::from_str(&query.module)?; - let (kv_key, response_code_id, query_type) = osmo_type.get_registration_config(query.params)?; + let (kv_key, response_code_id) = osmo_type.get_registration_config(query.params)?; let connection_id = CONNECTION_ID.load(deps.storage)?; @@ -110,7 +86,6 @@ fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> S let query = QueryRegistrationInfoResponse { registration_msg: kv_registration_msg, reply_id: response_code_id, - query_type, }; to_json_binary(&query) diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index f0e74140..065c85ce 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -1,24 +1,27 @@ use std::str::FromStr; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Binary, StdError, StdResult}; +use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; use neutron_sdk::{ bindings::types::KVKey, interchain_queries::{ helpers::decode_and_convert, + types::KVReconstruct, v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, }, }; +use osmosis_std::shim::Any; +use prost::Message; use serde_json::Value; -use valence_icq_lib_utils::{BankResultTypes, GammResultTypes, QueryResult}; +use valence_icq_lib_utils::QueryReconstructionRequest; use crate::error::ContractError; pub trait QueryTypeDefinition { const REPLY_ID: u64; - fn get_query_type(&self) -> QueryResult; fn get_kv_key(&self, params: serde_json::Map) -> StdResult; + fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult; } macro_rules! define_osmosis_types { @@ -32,7 +35,7 @@ macro_rules! define_osmosis_types { } impl FromStr for OsmosisTypes - where $($type: QueryTypeDefinition),* + where $($type: QueryTypeDefinition, )* { type Err = ContractError; @@ -47,18 +50,23 @@ macro_rules! define_osmosis_types { } impl OsmosisTypes { - pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64, QueryResult)> { + pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64)> { match self { $( OsmosisTypes::$variant(t) => Ok(( t.get_kv_key(params)?, - <$type>::REPLY_ID, - t.get_query_type() - )), + <$type>::REPLY_ID, )), )* } } - } + + pub fn reconstruct_response(&self, request: &QueryReconstructionRequest) -> StdResult { + match self { + $( + OsmosisTypes::$variant(_t) => <$type>::decode_and_reconstruct(request), + )* + } + }} }; } @@ -70,12 +78,6 @@ define_osmosis_types! { impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { const REPLY_ID: u64 = 31415; - fn get_query_type(&self) -> QueryResult { - QueryResult::Gamm { - result_type: GammResultTypes::Pool, - } - } - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { let pool_prefix_key: u8 = 0x02; let pool_id = match params["pool_id"].clone() { @@ -107,17 +109,26 @@ impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { key: Binary::new(pool_access_key), }) } + + fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { + let any_msg: Any = Any::decode(request.icq_result.kv_results[0].value.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = + any_msg.try_into().unwrap(); + + let json_str_pool = to_json_string(&osmo_pool)?; + + let json_value: Value = serde_json::from_str(&json_str_pool) + .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; + + Ok(json_value) + } } impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse { const REPLY_ID: u64 = 31416; - fn get_query_type(&self) -> QueryResult { - QueryResult::Bank { - result_type: BankResultTypes::AccountDenomBalance, - } - } - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { // let addr = params["addr"].to_string(); @@ -141,8 +152,6 @@ impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBal } }; - // let denom = params["denom"].to_string(); - let converted_addr_bytes = decode_and_convert(&addr).unwrap(); let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); @@ -152,6 +161,17 @@ impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBal key: Binary::new(balance_key), }) } + + fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { + let balances: neutron_sdk::interchain_queries::v047::types::Balances = + KVReconstruct::reconstruct(&request.icq_result.kv_results).unwrap(); + + let balances_str = to_json_string(&balances)?; + + let json_value: Value = serde_json::from_str(&balances_str).unwrap(); + + Ok(json_value) + } } #[cfg(test)] @@ -169,7 +189,7 @@ mod tests { let param_map = params.as_object().unwrap(); - let result = balance.get_kv_key(param_map.clone()).unwrap(); + let _result = balance.get_kv_key(param_map.clone()).unwrap(); } #[test] diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 0c1b3f81..8306a835 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -68,14 +68,14 @@ fn register_kv_query( let query_registration_resp: QueryRegistrationInfoResponse = deps.querier.query_wasm_smart( type_registry.to_string(), &DomainRegistryQueryMsg::GetRegistrationConfig(DomainRegistryQueryRequest { - module, + module: module.to_string(), params: query, }), )?; let query_cfg = PendingQueryIdConfig { associated_domain_registry: type_registry, - query_type: query_registration_resp.query_type.clone(), + query_type: module.to_string(), }; // here the key is set to the resp.reply_id just to get to the reply handler. diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs index bdc3c17b..022670b6 100644 --- a/packages/icq-querier-utils/src/lib.rs +++ b/packages/icq-querier-utils/src/lib.rs @@ -24,7 +24,7 @@ pub enum QueryMsg { #[cw_serde] pub struct QueryReconstructionRequest { pub icq_result: InterchainQueryResult, - pub query_type: QueryResult, + pub query_type: String, } #[cw_serde] @@ -34,7 +34,12 @@ pub struct QueryReconstructionResponse { #[cw_serde] pub struct QueryRegistrationInfoRequest { + /// module here refers to some string identifier of the query we want to perform. + /// one useful identifier is that of the proto type, e.g. `/osmosis.gamm.v1beta1.Pool`. + /// basically describes what type we are dealing with pub module: String, + /// params here describe the parameters to be passed into our query request. + /// if module above describes the what, these params describe the how. pub params: serde_json::Map, } @@ -42,27 +47,10 @@ pub struct QueryRegistrationInfoRequest { pub struct QueryRegistrationInfoResponse { pub registration_msg: NeutronMsg, pub reply_id: u64, - pub query_type: QueryResult, -} - -#[cw_serde] -pub enum QueryResult { - Gamm { result_type: GammResultTypes }, - Bank { result_type: BankResultTypes }, -} - -#[cw_serde] -pub enum GammResultTypes { - Pool, -} - -#[cw_serde] -pub enum BankResultTypes { - AccountDenomBalance, } #[cw_serde] pub struct PendingQueryIdConfig { pub associated_domain_registry: String, - pub query_type: QueryResult, + pub query_type: String, } From 9070486f6d38334de7ed559f655c9b5b57573ccc Mon Sep 17 00:00:00 2001 From: bekauz Date: Sun, 1 Dec 2024 20:11:14 +0100 Subject: [PATCH 60/92] cleanup; move global stuff to packages --- .../osmo_registry/src/contract.rs | 6 +- .../osmo_registry/src/error.rs | 4 + .../osmo_registry/src/msg.rs | 175 ++---------------- .../osmo_registry/src/testing/mod.rs | 2 +- .../osmo_registry/src/testing/tests.rs | 59 ++++++ packages/icq-querier-utils/src/lib.rs | 90 +++++++++ 6 files changed, 175 insertions(+), 161 deletions(-) create mode 100644 contracts/domain_type_registries/osmo_registry/src/testing/tests.rs diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index 78116c18..deb09083 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -11,7 +11,7 @@ use valence_icq_lib_utils::QueryRegistrationInfoRequest; use valence_icq_lib_utils::QueryRegistrationInfoResponse; use crate::error::ContractError; -use crate::msg::OsmosisTypes; +use crate::msg::DomainRegistryType; use crate::state::CONNECTION_ID; use valence_icq_lib_utils::ExecuteMsg as DomainRegistryExecuteMsg; @@ -57,7 +57,7 @@ pub fn query(deps: Deps, _env: Env, msg: DomainRegistryQueryMsg) -> StdResult StdResult { - let underlying_type = OsmosisTypes::from_str(&query.query_type)?; + let underlying_type = DomainRegistryType::from_str(&query.query_type)?; let reconstructed_json_value = underlying_type.reconstruct_response(&query)?; @@ -69,7 +69,7 @@ fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult StdResult { - let osmo_type = OsmosisTypes::from_str(&query.module)?; + let osmo_type = DomainRegistryType::from_str(&query.module)?; let (kv_key, response_code_id) = osmo_type.get_registration_config(query.params)?; diff --git a/contracts/domain_type_registries/osmo_registry/src/error.rs b/contracts/domain_type_registries/osmo_registry/src/error.rs index 7d49dc34..2f0176d4 100644 --- a/contracts/domain_type_registries/osmo_registry/src/error.rs +++ b/contracts/domain_type_registries/osmo_registry/src/error.rs @@ -1,4 +1,5 @@ use cosmwasm_std::StdError; +use serde_json::Value; use thiserror::Error; #[derive(Error, Debug)] @@ -14,6 +15,9 @@ pub enum ContractError { #[error("Unknown type URL: {0}")] UnknownTypeUrl(String), + + #[error("json field {0} missing from the query params: {1:?}")] + JsonFieldMissing(String, serde_json::Map), } impl From for StdError { diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index 065c85ce..2cfa3358 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -13,7 +13,9 @@ use neutron_sdk::{ use osmosis_std::shim::Any; use prost::Message; use serde_json::Value; -use valence_icq_lib_utils::QueryReconstructionRequest; +use valence_icq_lib_utils::{ + define_registry_types, get_str_query_param, get_u64_query_param, QueryReconstructionRequest, +}; use crate::error::ContractError; @@ -24,53 +26,7 @@ pub trait QueryTypeDefinition { fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult; } -macro_rules! define_osmosis_types { - ($(($variant:ident, $type:ty)),* $(,)?) => { - #[allow(clippy::large_enum_variant)] - #[cw_serde] - pub enum OsmosisTypes { - $( - $variant($type), - )* - } - - impl FromStr for OsmosisTypes - where $($type: QueryTypeDefinition, )* - { - type Err = ContractError; - - fn from_str(type_url: &str) -> Result { - match type_url { - $( - <$type>::TYPE_URL => Ok(OsmosisTypes::$variant(<$type>::default())), - )* - _ => Err(ContractError::UnknownTypeUrl(type_url.to_string())), - } - } - } - - impl OsmosisTypes { - pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64)> { - match self { - $( - OsmosisTypes::$variant(t) => Ok(( - t.get_kv_key(params)?, - <$type>::REPLY_ID, )), - )* - } - } - - pub fn reconstruct_response(&self, request: &QueryReconstructionRequest) -> StdResult { - match self { - $( - OsmosisTypes::$variant(_t) => <$type>::decode_and_reconstruct(request), - )* - } - }} - }; -} - -define_osmosis_types! { +define_registry_types! { (GammV1Beta1Pool, osmosis_std::types::osmosis::gamm::v1beta1::Pool), (BankV1Beta1Balance, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) } @@ -80,26 +36,8 @@ impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { fn get_kv_key(&self, params: serde_json::Map) -> StdResult { let pool_prefix_key: u8 = 0x02; - let pool_id = match params["pool_id"].clone() { - Value::Number(number) => match number.as_u64() { - Some(n) => n, - None => { - return Err(StdError::generic_err(format!( - "failed to parse {:?} as u64 for pool_id access", - number - ))) - } - }, - Value::String(str_num) => str_num.parse::().map_err(|_| { - StdError::generic_err(format!("failed to parse pool_id {:?} to u64", str_num)) - })?, - _ => { - return Err(StdError::generic_err(format!( - "field pool_id missing from query params: {:?}", - params - ))) - } - }; + + let pool_id = get_u64_query_param(¶ms, "pool_id")?; let mut pool_access_key = vec![pool_prefix_key]; pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); @@ -114,8 +52,9 @@ impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { let any_msg: Any = Any::decode(request.icq_result.kv_results[0].value.as_slice()) .map_err(|e| StdError::generic_err(e.to_string()))?; - let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = - any_msg.try_into().unwrap(); + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = any_msg + .try_into() + .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; let json_str_pool = to_json_string(&osmo_pool)?; @@ -130,30 +69,11 @@ impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBal const REPLY_ID: u64 = 31416; fn get_kv_key(&self, params: serde_json::Map) -> StdResult { - // let addr = params["addr"].to_string(); - - let addr = match params["addr"].clone() { - Value::String(address_str) => address_str, - _ => { - return Err(StdError::generic_err(format!( - "field addr missing from query params: {:?}", - params - ))) - } - }; - - let denom = match params["denom"].clone() { - Value::String(denom_str) => denom_str, - _ => { - return Err(StdError::generic_err(format!( - "field denom missing from query params: {:?}", - params - ))) - } - }; - - let converted_addr_bytes = decode_and_convert(&addr).unwrap(); + let addr = get_str_query_param(¶ms, "addr")?; + let denom = get_str_query_param(¶ms, "denom")?; + let converted_addr_bytes = decode_and_convert(&addr) + .map_err(|_| StdError::generic_err("failed to decode addr"))?; let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); Ok(KVKey { @@ -164,74 +84,15 @@ impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBal fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(&request.icq_result.kv_results).unwrap(); + KVReconstruct::reconstruct(&request.icq_result.kv_results).map_err(|e| { + StdError::generic_err(format!("failed to reconstruct query result: {:?}", e)) + })?; let balances_str = to_json_string(&balances)?; - let json_value: Value = serde_json::from_str(&balances_str).unwrap(); + let json_value: Value = serde_json::from_str(&balances_str) + .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; Ok(json_value) } } - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::json; - - #[test] - fn test_balance_get_kv_key() { - let balance = osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::default(); - let params = json!({ - "addr": "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63", - "denom": "uosmo" - }); - - let param_map = params.as_object().unwrap(); - - let _result = balance.get_kv_key(param_map.clone()).unwrap(); - } - - #[test] - fn test_json_map_serde() { - let params = json!({ - "pool_id": "1" - }); - - let json_restored: serde_json::Map = params.as_object().unwrap().clone(); - println!("json restored: {:?}", json_restored); - - let pool_id = json_restored["pool_id"].as_u64().unwrap(); - - println!("pool_id: {:?}", pool_id); - } - - #[test] - fn test_gamm_pool_get_kv_key() { - let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool::default(); - let params = json!({ - "pool_id": 1 - }); - - let param_str = params.to_string(); - - let json_restored: Value = serde_json::from_str(¶m_str).unwrap(); - println!("json restored: {:?}", json_restored); - - let pool_id = json_restored["pool_id"].as_u64().unwrap(); - - println!("pool_id: {:?}", pool_id); - - let param_map = params.as_object().unwrap(); - - let result = pool.get_kv_key(param_map.clone()).unwrap(); - - assert_eq!(result.path, "gamm"); - let expected_key = { - let mut key = vec![0x02]; - key.extend_from_slice(&1u64.to_be_bytes()); - key - }; - assert_eq!(result.key.as_slice(), expected_key.as_slice()); - } -} diff --git a/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs b/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs index 8b137891..14f00389 100644 --- a/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs +++ b/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs @@ -1 +1 @@ - +mod tests; diff --git a/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs b/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs new file mode 100644 index 00000000..73d3dc80 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs @@ -0,0 +1,59 @@ +use crate::msg::QueryTypeDefinition; + +use serde_json::{json, Value}; + +#[test] +fn test_balance_get_kv_key() { + let balance = osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::default(); + let params = json!({ + "addr": "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63", + "denom": "uosmo" + }); + + let param_map = params.as_object().unwrap(); + + let _result = balance.get_kv_key(param_map.clone()).unwrap(); +} + +#[test] +fn test_json_map_serde() { + let params = json!({ + "pool_id": "1" + }); + + let json_restored: serde_json::Map = params.as_object().unwrap().clone(); + println!("json restored: {:?}", json_restored); + + let pool_id = json_restored["pool_id"].as_u64().unwrap(); + + println!("pool_id: {:?}", pool_id); +} + +#[test] +fn test_gamm_pool_get_kv_key() { + let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool::default(); + let params = json!({ + "pool_id": 1 + }); + + let param_str = params.to_string(); + + let json_restored: Value = serde_json::from_str(¶m_str).unwrap(); + println!("json restored: {:?}", json_restored); + + let pool_id = json_restored["pool_id"].as_u64().unwrap(); + + println!("pool_id: {:?}", pool_id); + + let param_map = params.as_object().unwrap(); + + let result = pool.get_kv_key(param_map.clone()).unwrap(); + + assert_eq!(result.path, "gamm"); + let expected_key = { + let mut key = vec![0x02]; + key.extend_from_slice(&1u64.to_be_bytes()); + key + }; + assert_eq!(result.key.as_slice(), expected_key.as_slice()); +} diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs index 022670b6..296386fa 100644 --- a/packages/icq-querier-utils/src/lib.rs +++ b/packages/icq-querier-utils/src/lib.rs @@ -1,4 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{StdError, StdResult}; use neutron_sdk::bindings::{msg::NeutronMsg, types::InterchainQueryResult}; use serde_json::Value; @@ -54,3 +55,92 @@ pub struct PendingQueryIdConfig { pub associated_domain_registry: String, pub query_type: String, } + +/// macro to generate enums for types we wish to support in each domain +/// registry +#[macro_export] +macro_rules! define_registry_types { + ($(($variant:ident, $type:ty)),* $(,)?) => { + #[allow(clippy::large_enum_variant)] + #[cw_serde] + pub enum DomainRegistryType { + $( + $variant($type), + )* + } + + /// default implementation for a str parser to go from proto type url to + /// the actual type + impl FromStr for DomainRegistryType + where $($type: QueryTypeDefinition, )* + { + type Err = ContractError; + + fn from_str(type_url: &str) -> Result { + match type_url { + $( + <$type>::TYPE_URL => Ok(DomainRegistryType::$variant(<$type>::default())), + )* + _ => Err(ContractError::UnknownTypeUrl(type_url.to_string())), + } + } + } + + impl DomainRegistryType { + pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64)> { + match self { + $( + DomainRegistryType::$variant(t) => Ok(( + t.get_kv_key(params)?, + <$type>::REPLY_ID, )), + )* + } + } + + pub fn reconstruct_response(&self, request: &QueryReconstructionRequest) -> StdResult { + match self { + $( + DomainRegistryType::$variant(_t) => <$type>::decode_and_reconstruct(request), + )* + } + } + } + + }; +} + +pub fn get_u64_query_param(params: &serde_json::Map, key: &str) -> StdResult { + let value = match params.get(key) { + Some(Value::Number(number)) => number.as_u64().ok_or(StdError::generic_err(format!( + "failed to parse {:?} as u64 for {key} access", + number + ))), + Some(Value::String(str_num)) => str_num.parse::().map_err(|_| { + StdError::generic_err(format!( + "failed to parse {:?} to u64 for key {key}", + str_num + )) + }), + _ => Err(StdError::generic_err(format!( + "field pool_id missing from query params: {:?}", + params + ))), + }?; + + Ok(value) +} + +pub fn get_str_query_param( + params: &serde_json::Map, + key: &str, +) -> StdResult { + let value = match params.get(key) { + Some(Value::String(str_val)) => Ok(str_val), + _ => Err(StdError::generic_err(format!( + "field {key} missing from query params: {:?}", + params + ))), + }?; + + Ok(value.to_string()) +} From fee1217cec5c92a6dc0eec3a5ff79076e2ab21a6 Mon Sep 17 00:00:00 2001 From: bekauz Date: Sun, 1 Dec 2024 20:22:26 +0100 Subject: [PATCH 61/92] type_definitions mod --- .../osmo_registry/src/lib.rs | 1 + .../osmo_registry/src/msg.rs | 83 +------------------ .../bank_v1beta1_query_balance.rs | 45 ++++++++++ .../src/type_definitions/gamm_v1beta1_pool.rs | 42 ++++++++++ .../osmo_registry/src/type_definitions/mod.rs | 2 + 5 files changed, 93 insertions(+), 80 deletions(-) create mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs create mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs diff --git a/contracts/domain_type_registries/osmo_registry/src/lib.rs b/contracts/domain_type_registries/osmo_registry/src/lib.rs index 3274df2d..33258b89 100644 --- a/contracts/domain_type_registries/osmo_registry/src/lib.rs +++ b/contracts/domain_type_registries/osmo_registry/src/lib.rs @@ -5,3 +5,4 @@ mod testing; pub mod error; pub mod state; +pub mod type_definitions; diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index 2cfa3358..1930a50f 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -1,21 +1,10 @@ use std::str::FromStr; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; -use neutron_sdk::{ - bindings::types::KVKey, - interchain_queries::{ - helpers::decode_and_convert, - types::KVReconstruct, - v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, - }, -}; -use osmosis_std::shim::Any; -use prost::Message; +use cosmwasm_std::StdResult; +use neutron_sdk::bindings::types::KVKey; use serde_json::Value; -use valence_icq_lib_utils::{ - define_registry_types, get_str_query_param, get_u64_query_param, QueryReconstructionRequest, -}; +use valence_icq_lib_utils::{define_registry_types, QueryReconstructionRequest}; use crate::error::ContractError; @@ -30,69 +19,3 @@ define_registry_types! { (GammV1Beta1Pool, osmosis_std::types::osmosis::gamm::v1beta1::Pool), (BankV1Beta1Balance, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) } - -impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { - const REPLY_ID: u64 = 31415; - - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { - let pool_prefix_key: u8 = 0x02; - - let pool_id = get_u64_query_param(¶ms, "pool_id")?; - - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); - - Ok(KVKey { - path: "gamm".to_string(), - key: Binary::new(pool_access_key), - }) - } - - fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { - let any_msg: Any = Any::decode(request.icq_result.kv_results[0].value.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))?; - - let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = any_msg - .try_into() - .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; - - let json_str_pool = to_json_string(&osmo_pool)?; - - let json_value: Value = serde_json::from_str(&json_str_pool) - .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; - - Ok(json_value) - } -} - -impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse { - const REPLY_ID: u64 = 31416; - - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { - let addr = get_str_query_param(¶ms, "addr")?; - let denom = get_str_query_param(¶ms, "denom")?; - - let converted_addr_bytes = decode_and_convert(&addr) - .map_err(|_| StdError::generic_err("failed to decode addr"))?; - let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); - - Ok(KVKey { - path: BANK_STORE_KEY.to_string(), - key: Binary::new(balance_key), - }) - } - - fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { - let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(&request.icq_result.kv_results).map_err(|e| { - StdError::generic_err(format!("failed to reconstruct query result: {:?}", e)) - })?; - - let balances_str = to_json_string(&balances)?; - - let json_value: Value = serde_json::from_str(&balances_str) - .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; - - Ok(json_value) - } -} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs new file mode 100644 index 00000000..46acb8c3 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs @@ -0,0 +1,45 @@ +use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; +use neutron_sdk::{ + bindings::types::KVKey, + interchain_queries::{ + helpers::decode_and_convert, + types::KVReconstruct, + v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, + }, +}; +use serde_json::Value; +use valence_icq_lib_utils::{get_str_query_param, QueryReconstructionRequest}; + +use crate::msg::QueryTypeDefinition; + +impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse { + const REPLY_ID: u64 = 31416; + + fn get_kv_key(&self, params: serde_json::Map) -> StdResult { + let addr = get_str_query_param(¶ms, "addr")?; + let denom = get_str_query_param(¶ms, "denom")?; + + let converted_addr_bytes = decode_and_convert(&addr) + .map_err(|_| StdError::generic_err("failed to decode addr"))?; + let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); + + Ok(KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }) + } + + fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { + let balances: neutron_sdk::interchain_queries::v047::types::Balances = + KVReconstruct::reconstruct(&request.icq_result.kv_results).map_err(|e| { + StdError::generic_err(format!("failed to reconstruct query result: {:?}", e)) + })?; + + let balances_str = to_json_string(&balances)?; + + let json_value: Value = serde_json::from_str(&balances_str) + .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; + + Ok(json_value) + } +} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs new file mode 100644 index 00000000..f41f2fa9 --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs @@ -0,0 +1,42 @@ +use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; +use neutron_sdk::bindings::types::KVKey; +use osmosis_std::shim::Any; +use prost::Message; +use serde_json::Value; +use valence_icq_lib_utils::{get_u64_query_param, QueryReconstructionRequest}; + +use crate::msg::QueryTypeDefinition; + +impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { + const REPLY_ID: u64 = 31415; + + fn get_kv_key(&self, params: serde_json::Map) -> StdResult { + let pool_prefix_key: u8 = 0x02; + + let pool_id = get_u64_query_param(¶ms, "pool_id")?; + + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); + + Ok(KVKey { + path: "gamm".to_string(), + key: Binary::new(pool_access_key), + }) + } + + fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { + let any_msg: Any = Any::decode(request.icq_result.kv_results[0].value.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = any_msg + .try_into() + .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; + + let json_str_pool = to_json_string(&osmo_pool)?; + + let json_value: Value = serde_json::from_str(&json_str_pool) + .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; + + Ok(json_value) + } +} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs new file mode 100644 index 00000000..d478596e --- /dev/null +++ b/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs @@ -0,0 +1,2 @@ +pub mod bank_v1beta1_query_balance; +pub mod gamm_v1beta1_pool; From cd016803e0337bcdbc1ca0bfe3e2fadd1190aacf Mon Sep 17 00:00:00 2001 From: bekauz Date: Sun, 1 Dec 2024 20:51:01 +0100 Subject: [PATCH 62/92] move domain registry error to utils --- .../osmo_registry/src/contract.rs | 6 ++-- .../osmo_registry/src/error.rs | 30 ----------------- .../osmo_registry/src/lib.rs | 1 - .../osmo_registry/src/msg.rs | 2 -- contracts/libraries/icq-querier/src/lib.rs | 1 - .../libraries/icq-querier/src/utils/mod.rs | 1 - .../libraries/icq-querier/src/utils/types.rs | 1 - packages/icq-querier-utils/src/lib.rs | 33 +++++++++++++++++-- 8 files changed, 34 insertions(+), 41 deletions(-) delete mode 100644 contracts/domain_type_registries/osmo_registry/src/error.rs delete mode 100644 contracts/libraries/icq-querier/src/utils/mod.rs delete mode 100644 contracts/libraries/icq-querier/src/utils/types.rs diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs index deb09083..8fe9c378 100644 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ b/contracts/domain_type_registries/osmo_registry/src/contract.rs @@ -9,8 +9,8 @@ use valence_icq_lib_utils::QueryReconstructionRequest; use valence_icq_lib_utils::QueryReconstructionResponse; use valence_icq_lib_utils::QueryRegistrationInfoRequest; use valence_icq_lib_utils::QueryRegistrationInfoResponse; +use valence_icq_lib_utils::TypeRegistryError; -use crate::error::ContractError; use crate::msg::DomainRegistryType; use crate::state::CONNECTION_ID; @@ -28,7 +28,7 @@ pub fn instantiate( _env: Env, _info: MessageInfo, msg: DomainRegistryInstantiateMsg, -) -> Result { +) -> Result { CONNECTION_ID.save(deps.storage, &msg.connection_id)?; Ok(Response::default()) @@ -40,7 +40,7 @@ pub fn execute( _env: Env, _info: MessageInfo, _msg: DomainRegistryExecuteMsg, -) -> Result { +) -> Result { Ok(Response::default()) } diff --git a/contracts/domain_type_registries/osmo_registry/src/error.rs b/contracts/domain_type_registries/osmo_registry/src/error.rs deleted file mode 100644 index 2f0176d4..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/error.rs +++ /dev/null @@ -1,30 +0,0 @@ -use cosmwasm_std::StdError; -use serde_json::Value; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ContractError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Unknown reply id: {0}")] - UnknownReplyId(u64), - - #[error("Unsupported module: {0}")] - UnsupportedModule(String), - - #[error("Unknown type URL: {0}")] - UnknownTypeUrl(String), - - #[error("json field {0} missing from the query params: {1:?}")] - JsonFieldMissing(String, serde_json::Map), -} - -impl From for StdError { - fn from(val: ContractError) -> Self { - match val { - ContractError::Std(std_error) => std_error, - e => StdError::generic_err(e.to_string()), - } - } -} diff --git a/contracts/domain_type_registries/osmo_registry/src/lib.rs b/contracts/domain_type_registries/osmo_registry/src/lib.rs index 33258b89..1bbe50c6 100644 --- a/contracts/domain_type_registries/osmo_registry/src/lib.rs +++ b/contracts/domain_type_registries/osmo_registry/src/lib.rs @@ -3,6 +3,5 @@ pub mod msg; #[cfg(test)] mod testing; -pub mod error; pub mod state; pub mod type_definitions; diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs index 1930a50f..bfac1cad 100644 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ b/contracts/domain_type_registries/osmo_registry/src/msg.rs @@ -6,8 +6,6 @@ use neutron_sdk::bindings::types::KVKey; use serde_json::Value; use valence_icq_lib_utils::{define_registry_types, QueryReconstructionRequest}; -use crate::error::ContractError; - pub trait QueryTypeDefinition { const REPLY_ID: u64; diff --git a/contracts/libraries/icq-querier/src/lib.rs b/contracts/libraries/icq-querier/src/lib.rs index 98098cd8..3274df2d 100644 --- a/contracts/libraries/icq-querier/src/lib.rs +++ b/contracts/libraries/icq-querier/src/lib.rs @@ -5,4 +5,3 @@ mod testing; pub mod error; pub mod state; -pub mod utils; diff --git a/contracts/libraries/icq-querier/src/utils/mod.rs b/contracts/libraries/icq-querier/src/utils/mod.rs deleted file mode 100644 index cd408564..00000000 --- a/contracts/libraries/icq-querier/src/utils/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod types; diff --git a/contracts/libraries/icq-querier/src/utils/types.rs b/contracts/libraries/icq-querier/src/utils/types.rs deleted file mode 100644 index 8b137891..00000000 --- a/contracts/libraries/icq-querier/src/utils/types.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs index 296386fa..96d96361 100644 --- a/packages/icq-querier-utils/src/lib.rs +++ b/packages/icq-querier-utils/src/lib.rs @@ -56,6 +56,35 @@ pub struct PendingQueryIdConfig { pub query_type: String, } +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum TypeRegistryError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unknown reply id: {0}")] + UnknownReplyId(u64), + + #[error("Unsupported module: {0}")] + UnsupportedModule(String), + + #[error("Unknown type URL: {0}")] + UnknownTypeUrl(String), + + #[error("json field {0} missing from the query params: {1:?}")] + JsonFieldMissing(String, serde_json::Map), +} + +impl From for StdError { + fn from(val: TypeRegistryError) -> Self { + match val { + TypeRegistryError::Std(std_error) => std_error, + e => StdError::generic_err(e.to_string()), + } + } +} + /// macro to generate enums for types we wish to support in each domain /// registry #[macro_export] @@ -74,14 +103,14 @@ macro_rules! define_registry_types { impl FromStr for DomainRegistryType where $($type: QueryTypeDefinition, )* { - type Err = ContractError; + type Err = $crate::TypeRegistryError; fn from_str(type_url: &str) -> Result { match type_url { $( <$type>::TYPE_URL => Ok(DomainRegistryType::$variant(<$type>::default())), )* - _ => Err(ContractError::UnknownTypeUrl(type_url.to_string())), + _ => Err($crate::TypeRegistryError::UnknownTypeUrl(type_url.to_string())), } } } From ddb4185b5a89dbe9cdaccdec7c5fa64d87627c8d Mon Sep 17 00:00:00 2001 From: bekauz Date: Sun, 1 Dec 2024 22:29:29 +0100 Subject: [PATCH 63/92] init: basic rpm asserter logic --- .../libraries/icq-querier/src/contract.rs | 68 ++++++++++++++++ contracts/libraries/icq-querier/src/msg.rs | 4 + .../examples/interchain_querier.rs | 80 ++++++++++++++++++- 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 8306a835..2e15644e 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -56,6 +56,74 @@ pub fn execute( module, query, } => register_kv_query(deps, type_registry, module, query), + FunctionMsgs::AssertQueryResult { + query_id, + assertion, + } => assert_query_result(deps, query_id, assertion), + } +} + +fn assert_query_result( + deps: DepsMut, + query_id: u64, + assertion: Vec, // reverse polish notation +) -> Result, LibraryError> { + let query_result = QUERY_RESULTS.load(deps.storage, query_id)?; + + let mut stack = vec![]; + for token in assertion.clone() { + match token.as_str() { + // operators + "==" => { + let b = stack.pop().unwrap(); + let a = stack.pop().unwrap(); + stack.push((a == b).to_string()); + } + "!=" => { + let b = stack.pop().unwrap(); + let a = stack.pop().unwrap(); + stack.push((a != b).to_string()); + } + ">" => { + let b = stack.pop().unwrap(); + let a = stack.pop().unwrap(); + stack.push((a > b).to_string()); + } + "<" => { + let b = stack.pop().unwrap(); + let a = stack.pop().unwrap(); + stack.push((a < b).to_string()); + } + // TODO: bunch of stuff here is missing like &&, ||, etc. + // operands + _ => { + if token.starts_with('/') { + let result = query_result.pointer(&token).unwrap(); + stack.push(result.to_string()); + } else { + stack.push(token.to_string()); + } + } + } + } + + if stack.len() == 1 { + let val = stack.pop().unwrap(); + if val == "true" { + Ok(Response::default() + .add_attribute("query_result", "true") + .add_attribute("for_assertion", assertion.join(" "))) + } else { + Err(LibraryError::Std(StdError::generic_err(format!( + "assertion failed, stack is non empty: {:?}", + stack + )))) + } + } else { + Err(LibraryError::Std(StdError::generic_err(format!( + "assertion failed, stack is non empty: {:?}", + stack + )))) } } diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index 4ef57b7a..2d077686 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -18,6 +18,10 @@ pub enum FunctionMsgs { // json string of the query query: serde_json::Map, }, + AssertQueryResult { + query_id: u64, + assertion: Vec, + }, } #[valence_library_query] diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index dbe8719a..15995c8a 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -182,8 +182,9 @@ fn main() -> Result<(), Box> { ); let mut results_found = false; + let mut results = vec![]; while !results_found { - let results = query_results(&test_ctx, icq_test_lib.address.to_string())?; + results = query_results(&test_ctx, icq_test_lib.address.to_string())?; if results.len() == 2 { info!("results: {:?}", results); @@ -194,9 +195,86 @@ fn main() -> Result<(), Box> { } } + let resp_1 = assert_icq_result( + &test_ctx, + icq_test_lib.address.to_string(), + results[0].0, + vec![ + "/pool_assets/0/token/amount".to_string(), + "/pool_assets/1/token/amount".to_string(), + "==".to_string(), + ], + )?; + + std::thread::sleep(Duration::from_secs(3)); + info!("assertion #1 result: {:?}", resp_1); + + let balance_amount: String = results[1] + .1 + .pointer("/coins/0/amount") + .unwrap() + .as_str() + .unwrap() + .to_string(); + info!("passing balance for assertion: {balance_amount}"); + let resp_2 = assert_icq_result( + &test_ctx, + icq_test_lib.address.to_string(), + results[1].0, + vec![ + "/coins/0/amount".to_string(), + balance_amount, // passing true + "==".to_string(), + ], + )?; + std::thread::sleep(Duration::from_secs(3)); + + info!("assertion #2 result: {:?}", resp_2); + + let resp_3 = assert_icq_result( + &test_ctx, + icq_test_lib.address.to_string(), + results[1].0, + vec![ + "/coins/0/amount".to_string(), + "314".to_string(), // passing false assertion value + "==".to_string(), + ], + )?; + std::thread::sleep(Duration::from_secs(3)); + + info!("assertion #3 result: {:?}", resp_3); + Ok(()) } +pub fn assert_icq_result( + test_ctx: &TestContext, + icq_lib: String, + query_id: u64, + assertion: Vec, +) -> Result { + let icq_assertion_msg = FunctionMsgs::AssertQueryResult { + query_id, + assertion, + }; + + let stringified_msg = serde_json::to_string(&icq_assertion_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + + info!("asserting query {query_id} result: {stringified_msg}"); + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &stringified_msg, + "--amount 1000000untrn --gas 50000000", + ) +} + pub fn register_kvq( test_ctx: &TestContext, icq_lib: String, From d5dc81e40fa7054e81603d7a69ed10f39a43f2cc Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 2 Dec 2024 20:17:02 +0100 Subject: [PATCH 64/92] add bank query unit tests --- .../bank_v1beta1_query_balance.rs | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs index 46acb8c3..cbb7ea4a 100644 --- a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs +++ b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; +use cosmwasm_std::{from_base64, from_json, to_json_string, Binary, StdError, StdResult}; use neutron_sdk::{ bindings::types::KVKey, interchain_queries::{ @@ -7,6 +7,8 @@ use neutron_sdk::{ v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, }, }; +use osmosis_std::{shim::Any, types::cosmos::bank::v1beta1::QueryBalanceResponse}; +use prost::Message; use serde_json::Value; use valence_icq_lib_utils::{get_str_query_param, QueryReconstructionRequest}; @@ -43,3 +45,60 @@ impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBal Ok(json_value) } } + +#[cfg(test)] +mod tests { + use super::*; + use neutron_sdk::bindings::types::StorageValue; + use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; + use serde_json::json; + + #[test] + fn test_get_kv_key() { + let mut params = serde_json::Map::new(); + params.insert( + "addr".to_string(), + json!("osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"), + ); + params.insert("denom".to_string(), json!("uosmo")); + + let qb_response = QueryBalanceResponse::default(); + let kvk_response = qb_response.get_kv_key(params).unwrap(); + + let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); + + assert_eq!(kvk_response.path, "bank".to_string()); + assert_eq!(kvk_response.key, key_binary); + } + + #[test] + fn test_decode_and_reconstruct() { + let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); + let value_binary = Binary::from_base64("OTk5ODg5OTk5NzUwMA==").unwrap(); + + let request = QueryReconstructionRequest { + icq_result: neutron_sdk::bindings::types::InterchainQueryResult { + kv_results: vec![StorageValue { + key: key_binary, + value: value_binary, + storage_prefix: "bank".to_string(), + }], + height: 1, + revision: 1, + }, + query_type: QueryBalanceResponse::TYPE_URL.to_string(), + }; + + let result = QueryBalanceResponse::decode_and_reconstruct(&request).unwrap(); + + let expected_json = json!({ + "coins": [ + { + "amount": "9998899997500", + "denom": "uosmo" + } + ] + }); + assert_eq!(result, expected_json); + } +} From 8c28d9c70053d1da14c482df92a5f33f9d1444e8 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 12 Dec 2024 18:03:39 +0100 Subject: [PATCH 65/92] init middleware utils package --- Cargo.lock | 8 +++ Cargo.toml | 1 + packages/middleware-utils/Cargo.toml | 10 ++++ packages/middleware-utils/src/lib.rs | 1 + .../middleware-utils/src/middleware_base.rs | 52 +++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 packages/middleware-utils/Cargo.toml create mode 100644 packages/middleware-utils/src/lib.rs create mode 100644 packages/middleware-utils/src/middleware_base.rs diff --git a/Cargo.lock b/Cargo.lock index aee9931b..4e194752 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5308,6 +5308,14 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "valence-middleware-utils" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", +] + [[package]] name = "valence-neutron-ibc-transfer-library" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index ee1695bd..7097e50b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ valence-program-registry-utils = { path = "packages/program-registry-utils" } valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } valence-icq-lib-utils = { path = "packages/icq-querier-utils" } +valence-middleware-utils = { path = "packages/middleware-utils" } # domain type registries valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } diff --git a/packages/middleware-utils/Cargo.toml b/packages/middleware-utils/Cargo.toml new file mode 100644 index 00000000..aad666e8 --- /dev/null +++ b/packages/middleware-utils/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "valence-middleware-utils" +version = { workspace = true } +edition = { workspace = true } +authors = ["Timewave Labs"] +description = "valence middleware utilities" + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs new file mode 100644 index 00000000..fd2ec330 --- /dev/null +++ b/packages/middleware-utils/src/lib.rs @@ -0,0 +1 @@ +pub mod middleware_base; diff --git a/packages/middleware-utils/src/middleware_base.rs b/packages/middleware-utils/src/middleware_base.rs new file mode 100644 index 00000000..27d5e122 --- /dev/null +++ b/packages/middleware-utils/src/middleware_base.rs @@ -0,0 +1,52 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Binary, CosmosMsg, Empty, SubMsgResponse, Uint64}; + +#[cw_serde] +pub enum PolytoneExecuteMsg { + Execute { + msgs: Vec>, + callback: Option, + timeout_seconds: Uint64, + }, +} + +#[cw_serde] +pub struct CallbackRequest { + pub receiver: String, + pub msg: Binary, +} + +#[cw_serde] +pub struct CallbackMessage { + /// Initaitor on the note chain. + pub initiator: Addr, + /// Message sent by the initaitor. This _must_ be base64 encoded + /// or execution will fail. + pub initiator_msg: Binary, + /// Data from the host chain. + pub result: Callback, +} + +#[cw_serde] +pub enum Callback { + Query(Result, ErrorResponse>), + Execute(Result), + FatalError(String), +} + +#[cw_serde] +pub struct ExecutionResponse { + /// The address on the remote chain that executed the messages. + pub executed_by: String, + /// Index `i` corresponds to the result of executing the `i`th + /// message. + pub result: Vec, +} + +#[cw_serde] +pub struct ErrorResponse { + /// The index of the first message who's execution failed. + pub message_index: Uint64, + /// The error that occured executing the message. + pub error: String, +} From a0286b36abd65b4f423e7d2939ad3fd616d9618d Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 12 Dec 2024 18:43:48 +0100 Subject: [PATCH 66/92] setup base osmosis middleware contract --- Cargo.lock | 19 +++++++++++ Cargo.toml | 5 ++- .../bank_v1beta1_query_balance.rs | 4 +-- .../osmosis/osmo-26-0-0/.cargo/config.toml | 3 ++ .../domains/osmosis/osmo-26-0-0/Cargo.toml | 31 +++++++++++++++++ .../domains/osmosis/osmo-26-0-0/README.md | 1 + .../osmosis/osmo-26-0-0/src/contract.rs | 34 +++++++++++++++++++ .../domains/osmosis/osmo-26-0-0/src/lib.rs | 2 ++ .../domains/osmosis/osmo-26-0-0/src/msg.rs | 12 +++++++ 9 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/README.md create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs diff --git a/Cargo.lock b/Cargo.lock index 4e194752..ee5cb17f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5308,6 +5308,25 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "valence-middleware-osmosis" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-ownable", + "cw-storage-plus 2.0.0", + "neutron-sdk", + "osmosis-std", + "osmosis-std-derive", + "osmosis-test-tube", + "prost 0.13.3", + "prost-types 0.13.3", + "serde-json-wasm 1.0.1", + "serde_json", + "thiserror 1.0.69", +] + [[package]] name = "valence-middleware-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 7097e50b..1a1b1b3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ members = [ "contracts/processor", "contracts/testing/*", "contracts/program-registry", - "contracts/domain_type_registries/*", + "contracts/middleware/domains/osmosis/osmo-26-0-0", "packages/*", "program-manager", "local-interchaintest", @@ -75,6 +75,9 @@ valence-osmosis-cl-lper = { path = "contracts/libraries/osmosis-cl- valence-osmosis-cl-withdrawer = { path = "contracts/libraries/osmosis-cl-withdrawer", features = ["library"] } valence-icq-querier = { path = "contracts/libraries/icq-querier", features = ["library"] } +# middleware +valence-middleware-osmosis = { path = "contracts/middleware/domains/osmosis/osmo-26-0-0", features = ["library"] } + # our packages valence-account-utils = { path = "packages/account-utils" } valence-astroport-utils = { path = "packages/astroport-utils" } diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs index cbb7ea4a..478a07a1 100644 --- a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs +++ b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{from_base64, from_json, to_json_string, Binary, StdError, StdResult}; +use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; use neutron_sdk::{ bindings::types::KVKey, interchain_queries::{ @@ -7,8 +7,6 @@ use neutron_sdk::{ v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, }, }; -use osmosis_std::{shim::Any, types::cosmos::bank::v1beta1::QueryBalanceResponse}; -use prost::Message; use serde_json::Value; use valence_icq_lib_utils::{get_str_query_param, QueryReconstructionRequest}; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml b/contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml new file mode 100644 index 00000000..5f6aa466 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml @@ -0,0 +1,3 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +schema = "run --bin schema" diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml new file mode 100644 index 00000000..d7864f1b --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "valence-middleware-osmosis" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +version = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-ownable = { workspace = true } +osmosis-std = "0.26.0" +osmosis-std-derive = "0.26.0" +prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } +prost-types = { version = "0.13.3", default-features = false } +neutron-sdk = { workspace = true } +serde-json-wasm = { version = "1.0.0", default-features = false } +thiserror = { workspace = true } +serde_json = { workspace = true } +cw-storage-plus = { workspace = true } + +[dev-dependencies] +osmosis-test-tube = { workspace = true } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/README.md b/contracts/middleware/domains/osmosis/osmo-26-0-0/README.md new file mode 100644 index 00000000..e2b0ee8f --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/README.md @@ -0,0 +1 @@ +# Osmosis middleware diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs new file mode 100644 index 00000000..7b0bad20 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -0,0 +1,34 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; + +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +// version info for migration info +const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: ExecuteMsg, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + Binary::from_base64("a") +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs new file mode 100644 index 00000000..112ecadc --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs @@ -0,0 +1,2 @@ +pub mod contract; +pub mod msg; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs new file mode 100644 index 00000000..86f8f599 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs @@ -0,0 +1,12 @@ +// TODO: declare select types for osmosis-std + +use cosmwasm_schema::cw_serde; + +#[cw_serde] +pub struct InstantiateMsg {} + +#[cw_serde] +pub enum ExecuteMsg {} + +#[cw_serde] +pub enum QueryMsg {} From a43aacd2d26de31c345fdcaa3bea5d71fadae5fa Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 13 Dec 2024 18:31:10 +0100 Subject: [PATCH 67/92] base valence xyk pool & osmo gamm adapters --- .../osmosis/osmo-26-0-0/src/contract.rs | 31 ++- .../domains/osmosis/osmo-26-0-0/src/lib.rs | 3 + .../osmosis/osmo-26-0-0/src/middleware.rs | 31 +++ .../domains/osmosis/osmo-26-0-0/src/msg.rs | 17 +- .../osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs | 249 ++++++++++++++++++ .../domains/osmosis/osmo-26-0-0/src/xyk.rs | 77 ++++++ 6 files changed, 401 insertions(+), 7 deletions(-) create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 7b0bad20..d265465f 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -1,8 +1,15 @@ +use std::collections::BTreeMap; + #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; +use cosmwasm_std::{ + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, +}; -use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use crate::{ + msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, + xyk::ValenceXykPool, +}; // version info for migration info const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); @@ -30,5 +37,23 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - Binary::from_base64("a") + match msg { + QueryMsg::Serialize { obj } => try_serialize_obj(obj), + QueryMsg::Deserialize { type_url, binary } => { + let deser = try_deserialize_type_url(type_url, binary)?; + to_json_binary(&deser) + } + } +} + +fn try_serialize_obj(object: ValenceXykPool) -> StdResult { + Ok(Binary::new("a".as_bytes().to_vec())) +} + +fn try_deserialize_type_url(type_url: String, binary: Binary) -> StdResult { + Ok(ValenceXykPool { + assets: vec![], + total_shares: "hi".to_string(), + domain_specific_fields: BTreeMap::new(), + }) } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs index 112ecadc..21c01d66 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs @@ -1,2 +1,5 @@ pub mod contract; +pub mod middleware; pub mod msg; +pub mod osmo_gamm_pool; +pub mod xyk; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs new file mode 100644 index 00000000..72a83742 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs @@ -0,0 +1,31 @@ +use std::collections::BTreeMap; + +use cosmwasm_schema::serde::de::DeserializeOwned; +use cosmwasm_std::{from_json, StdError, StdResult}; + +// fn process_pool>(external_pool: T) { +// // let valence_pool = external_pool.to_valence_xyk_pool(); +// } + +// trait ValenceMiddlewareTypeDefinition { +// fn serialize(&self) -> Binary; +// fn deserialize(&self) -> Self; +// } + +pub fn try_unpack_domain_specific_value( + key: &str, + domain_specific_fields: &BTreeMap, +) -> StdResult +where + T: DeserializeOwned, +{ + let binary = domain_specific_fields + .get(key) + .ok_or(StdError::generic_err(format!( + "failed to get {} field from domain specific fields", + key + ))) + .unwrap(); + + from_json(binary) +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs index 86f8f599..a8377604 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs @@ -1,12 +1,21 @@ -// TODO: declare select types for osmosis-std +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Binary; -use cosmwasm_schema::cw_serde; +use crate::xyk::ValenceXykPool; #[cw_serde] pub struct InstantiateMsg {} - #[cw_serde] pub enum ExecuteMsg {} #[cw_serde] -pub enum QueryMsg {} +#[derive(QueryResponses)] +pub enum QueryMsg { + /// serialize a message to binary + #[returns(Binary)] + Serialize { obj: ValenceXykPool }, + /// deserialize a message from binary/bytes + #[returns(ValenceXykPool)] + Deserialize { type_url: String, binary: Binary }, + // TODO: transform an outdated type to a new version +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs new file mode 100644 index 00000000..134fb190 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs @@ -0,0 +1,249 @@ +pub mod valence_xyk_type { + use std::collections::BTreeMap; + use std::str::FromStr; + + use crate::{middleware::try_unpack_domain_specific_value, xyk::ValenceXykPool}; + use cosmwasm_std::to_json_binary; + use cosmwasm_std::{StdError, Uint128}; + use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + use osmosis_std::types::osmosis::gamm::v1beta1::PoolParams; + use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; + + impl TryFrom for ValenceXykPool { + type Error = StdError; + + fn try_from(pool: Pool) -> Result { + // pack all the domain-specific fields + let mut domain_specific_fields = BTreeMap::from([ + ("address".to_string(), to_json_binary(&pool.address)?), + ("id".to_string(), to_json_binary(&pool.id)?), + ( + "future_pool_governor".to_string(), + to_json_binary(&pool.future_pool_governor)?, + ), + ( + "total_weight".to_string(), + to_json_binary(&pool.total_weight)?, + ), + ( + "pool_params".to_string(), + to_json_binary(&pool.pool_params)?, + ), + ]); + + if let Some(shares) = &pool.total_shares { + domain_specific_fields + .insert("shares_denom".to_string(), to_json_binary(&shares.denom)?); + } + + for asset in &pool.pool_assets { + if let Some(token) = &asset.token { + domain_specific_fields.insert( + format!("pool_asset_{}_weight", token.denom), + to_json_binary(&asset.weight)?, + ); + } + } + + let assets = pool + .pool_assets + .into_iter() + .filter_map(|asset| { + asset.token.map(|token| { + cosmwasm_std::coin( + Uint128::from_str(&token.amount).unwrap().into(), + token.denom, + ) + }) + }) + .collect(); + + let total_shares = pool + .total_shares + .map(|shares| shares.amount) + .unwrap_or_default(); + + Ok(ValenceXykPool { + assets, + total_shares, + domain_specific_fields, + }) + } + } + + impl TryFrom for Pool { + type Error = StdError; + + fn try_from(value: ValenceXykPool) -> Result { + // unpack the pool address + let address: String = + try_unpack_domain_specific_value("address", &value.domain_specific_fields)?; + + // unpack the pool id + let id: u64 = try_unpack_domain_specific_value("id", &value.domain_specific_fields)?; + + // unpack the future pool governor + let future_pool_governor: String = try_unpack_domain_specific_value( + "future_pool_governor", + &value.domain_specific_fields, + )?; + + // unpack the pool params + let pool_params: Option = + try_unpack_domain_specific_value("pool_params", &value.domain_specific_fields)?; + + // unpack the shares denom and total shares amount before combining them to a proto coin + let shares_denom: String = + try_unpack_domain_specific_value("shares_denom", &value.domain_specific_fields)?; + let shares_coin = Coin { + denom: shares_denom, + amount: value.total_shares, + }; + + // unpack the total weight + let total_weight: String = + try_unpack_domain_specific_value("total_weight", &value.domain_specific_fields)?; + + // unpack the pool assets + let pool_assets: Vec = value + .assets + .iter() + .map(|asset| { + let coin = Coin { + denom: asset.denom.to_string(), + amount: asset.amount.into(), + }; + + let weight: String = try_unpack_domain_specific_value( + &format!("pool_asset_{}_weight", asset.denom), + &value.domain_specific_fields, + ) + .unwrap(); + + PoolAsset { + token: Some(coin), + weight, + } + }) + .collect(); + + Ok(Pool { + address, + id, + pool_params, + future_pool_governor, + total_shares: Some(shares_coin), + pool_assets, + total_weight, + }) + } + } + + #[cfg(test)] + mod tests { + use super::*; + use cosmwasm_std::{coin, to_json_binary}; + use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + use std::collections::BTreeMap; + + #[test] + fn test_try_into() { + let domain_specific_fields = BTreeMap::from([ + ("address".to_string(), to_json_binary("pool1").unwrap()), + ("id".to_string(), to_json_binary(&1).unwrap()), + ( + "future_pool_governor".to_string(), + to_json_binary("gov1").unwrap(), + ), + ("total_weight".to_string(), to_json_binary("100").unwrap()), + ( + "pool_asset_uatom_weight".to_string(), + to_json_binary("120").unwrap(), + ), + ( + "pool_asset_uosmo_weight".to_string(), + to_json_binary("80").unwrap(), + ), + ( + "shares_denom".to_string(), + to_json_binary("osmo/gamm/whatever").unwrap(), + ), + ( + "pool_params".to_string(), + to_json_binary(&Some(PoolParams { + swap_fee: "0.003".to_string(), + exit_fee: "0.0".to_string(), + smooth_weight_change_params: None, + })) + .unwrap(), + ), + ("total_weight".to_string(), to_json_binary("100").unwrap()), + ]); + + let pool = ValenceXykPool { + assets: vec![coin(100, "uatom"), coin(200, "uosmo")], + total_shares: "1000".to_string(), + domain_specific_fields, + }; + + let osmosis_pool: Pool = pool.try_into().unwrap(); + + println!("osmosis_pool: {:?}", osmosis_pool); + assert_eq!(osmosis_pool.address, "pool1"); + assert_eq!(osmosis_pool.id, 1); + assert_eq!(osmosis_pool.future_pool_governor, "gov1"); + assert_eq!(osmosis_pool.total_weight, "100"); + assert_eq!(osmosis_pool.pool_assets.len(), 2); + assert_eq!(osmosis_pool.pool_assets[0].weight, "120"); + assert_eq!(osmosis_pool.pool_assets[1].weight, "80"); + let total_shares = osmosis_pool.total_shares.unwrap(); + assert_eq!(total_shares.amount, "1000"); + assert_eq!(total_shares.denom, "osmo/gamm/whatever"); + assert_eq!(osmosis_pool.pool_params.unwrap().swap_fee, "0.003"); + } + + #[test] + fn test_try_from() { + let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool { + address: "pool1".to_string(), + id: 1, + pool_params: Some(PoolParams { + swap_fee: "0.003".to_string(), + exit_fee: "0.0".to_string(), + smooth_weight_change_params: None, + }), + future_pool_governor: "gov1".to_string(), + total_shares: Some(Coin { + denom: "osmo/gamm/whatever".to_string(), + amount: "1000".to_string(), + }), + pool_assets: vec![ + PoolAsset { + token: Some(Coin { + denom: "uatom".to_string(), + amount: "100".to_string(), + }), + weight: "120".to_string(), + }, + PoolAsset { + token: Some(Coin { + denom: "uosmo".to_string(), + amount: "200".to_string(), + }), + weight: "80".to_string(), + }, + ], + total_weight: "100".to_string(), + }; + + let valence_xyk_pool = ValenceXykPool::try_from(pool).unwrap(); + + println!("parsed xyk pool: {:?}", valence_xyk_pool); + + assert_eq!(valence_xyk_pool.assets.len(), 2); + assert_eq!(valence_xyk_pool.assets[0], coin(100, "uatom")); + assert_eq!(valence_xyk_pool.assets[1], coin(200, "uosmo")); + assert_eq!(valence_xyk_pool.total_shares, "1000"); + } + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs new file mode 100644 index 00000000..13181391 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs @@ -0,0 +1,77 @@ +use std::collections::BTreeMap; + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Binary, Coin}; + +#[cw_serde] +pub struct ValenceXykPool { + /// assets in the pool + pub assets: Vec, + /// total amount of shares issued + pub total_shares: String, + /// any other fields that are unique to the external pool type + /// being represented by this struct + pub domain_specific_fields: BTreeMap, +} + +/* +OSMOSIS POOL + +pub struct Pool { + #[prost(string, tag = "1")] + pub address: ::prost::alloc::string::String, + #[prost(uint64, tag = "2")] + #[serde(alias = "ID")] + #[serde( + serialize_with = "crate::serde::as_str::serialize", + deserialize_with = "crate::serde::as_str::deserialize" + )] + pub id: u64, + #[prost(message, optional, tag = "3")] + pub pool_params: ::core::option::Option, + /// This string specifies who will govern the pool in the future. + /// Valid forms of this are: + /// {token name},{duration} + /// {duration} + /// where {token name} if specified is the token which determines the + /// governor, and if not specified is the LP token for this pool.duration is + /// a time specified as 0w,1w,2w, etc. which specifies how long the token + /// would need to be locked up to count in governance. 0w means no lockup. + /// TODO: Further improve these docs + #[prost(string, tag = "4")] + pub future_pool_governor: ::prost::alloc::string::String, + /// sum of all LP tokens sent out + #[prost(message, optional, tag = "5")] + pub total_shares: ::core::option::Option, + /// These are assumed to be sorted by denomiation. + /// They contain the pool asset and the information about the weight + #[prost(message, repeated, tag = "6")] + pub pool_assets: ::prost::alloc::vec::Vec, + /// sum of all non-normalized pool weights + #[prost(string, tag = "7")] + pub total_weight: ::prost::alloc::string::String, +} +*/ + +/* + ASTROPORT POOL: + "assets": [ + { + "info": { + "native_token": { + "denom": "uluna" + } + }, + "amount": "50487988152" + }, + { + "info": { + "token": { + "contract_addr": "terra13c7t0xtfpafcr6gae9f404x5am7euf87c9qwmsphsecamqjjujqs7yfm4m" + } + }, + "amount": "648612030411" + } + ], + "total_share": "177335913519" +*/ From 2bc238dd42eb5dd34b3d29868076fb47bb33273c Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 13 Dec 2024 19:08:10 +0100 Subject: [PATCH 68/92] extend middleware with icq type conversion --- .../osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs index 134fb190..0580458b 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs @@ -247,3 +247,203 @@ pub mod valence_xyk_type { } } } + +pub mod icq { + use std::collections::BTreeMap; + + use cosmwasm_std::{to_json_binary, Binary, StdError, StdResult}; + use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; + use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; + + use crate::middleware::try_unpack_domain_specific_value; + use prost::Message; + + pub trait IcqIntegration { + fn get_kv_key(&self, params: BTreeMap) -> StdResult; + fn decode_and_reconstruct( + query_id: String, + icq_result: InterchainQueryResult, + ) -> StdResult; + } + + impl IcqIntegration for Pool { + fn get_kv_key(&self, params: BTreeMap) -> StdResult { + let pool_prefix_key: u8 = 0x02; + + let id: u64 = try_unpack_domain_specific_value("pool_id", ¶ms)?; + + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&id.to_be_bytes()); + + Ok(KVKey { + path: "gamm".to_string(), + key: Binary::new(pool_access_key), + }) + } + + fn decode_and_reconstruct( + query_id: String, + icq_result: InterchainQueryResult, + ) -> StdResult { + let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + let osmo_pool: Pool = any_msg + .try_into() + .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; + + to_json_binary(&osmo_pool) + } + } + + #[cfg(test)] + mod tests { + use super::*; + use cosmwasm_std::{from_json, to_json_binary, Binary}; + use neutron_sdk::bindings::types::StorageValue; + use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolAsset, PoolParams}; + + #[test] + fn test_get_kv_key() { + let pool = Pool::default(); + let mut params = BTreeMap::new(); + params.insert("pool_id".to_string(), to_json_binary(&1u64).unwrap()); + + let kv_key = pool.get_kv_key(params).unwrap(); + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + assert_eq!(kv_key.path, "gamm"); + assert_eq!(kv_key.key, Binary::new(vec![2, 0, 0, 0, 0, 0, 0, 0, 1])); + assert_eq!(kv_key.key, binary_key); + } + + #[test] + fn test_decode_and_reconstruct() { + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "gamm".to_string(), + key: binary_key, + value: binary_value, + }; + + let osmo_pool_binary = Pool::decode_and_reconstruct( + Pool::TYPE_URL.to_string(), + InterchainQueryResult { + kv_results: vec![storage_value], + height: 1, + revision: 1, + }, + ) + .unwrap(); + + let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); + + assert_eq!( + osmo_pool.address, + "osmo19e2mf7cywkv7zaug6nk5f87d07fxrdgrladvymh2gwv5crvm3vnsuewhh7".to_string() + ); + assert_eq!(osmo_pool.id, 1); + assert_eq!( + osmo_pool.pool_params, + Some(PoolParams { + swap_fee: "0".to_string(), + exit_fee: "0".to_string(), + smooth_weight_change_params: None + }) + ); + assert_eq!(osmo_pool.future_pool_governor, "128h".to_string()); + assert_eq!( + osmo_pool.total_shares, + Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: "gamm/pool/1".to_string(), + amount: "100000000000000000000".to_string() + }) + ); + assert_eq!(osmo_pool.pool_assets.len(), 2); + assert_eq!( + osmo_pool.pool_assets[0], + PoolAsset { + token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: + "ibc/4E41ED8F3DCAEA15F4D6ADC6EDD7C04A676160735C9710B904B7BF53525B56D6" + .to_string(), + amount: "100000000".to_string() + }), + weight: "1073741824".to_string() + } + ); + assert_eq!( + osmo_pool.pool_assets[1], + PoolAsset { + token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: "uosmo".to_string(), + amount: "100000000".to_string() + }), + weight: "1073741824".to_string() + } + ); + assert_eq!(osmo_pool.total_weight, "2147483648"); + } + } +} + +#[cfg(test)] +mod tests { + use cosmwasm_std::{from_json, Binary}; + use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; + use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + + use crate::xyk::ValenceXykPool; + + use super::icq::IcqIntegration; + + #[test] + fn e2e() { + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "gamm".to_string(), + key: binary_key, + value: binary_value, + }; + + // first we simulate the icq result reconstruction of b64(proto) -> type -> b64(type) + let osmo_pool_binary = Pool::decode_and_reconstruct( + Pool::TYPE_URL.to_string(), + InterchainQueryResult { + kv_results: vec![storage_value], + height: 1, + revision: 1, + }, + ) + .unwrap(); + + // unpack the binary into a type + let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); + + // parse the external type into a valence type + let mut valence_pool: ValenceXykPool = osmo_pool.try_into().unwrap(); + + // simulate modifying the pool instance + valence_pool.assets.push(cosmwasm_std::coin(100, "batom")); + valence_pool.domain_specific_fields.insert( + "pool_asset_batom_weight".to_string(), + cosmwasm_std::to_json_binary(&"120").unwrap(), + ); + + // convert the valence type back into the external type + let osmo_pool: Pool = valence_pool.try_into().unwrap(); + + assert_eq!(osmo_pool.pool_assets.len(), 3); + } +} From 1d4a851567e5fa419e5310bc5c1d0f570b377365 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 12:58:18 +0100 Subject: [PATCH 69/92] const out the strings --- .../osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs index 0580458b..1460e676 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs @@ -9,31 +9,38 @@ pub mod valence_xyk_type { use osmosis_std::types::osmosis::gamm::v1beta1::PoolParams; use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; + const ADDRESS_KEY: &str = "address"; + const ID_KEY: &str = "id"; + const FUTURE_POOL_GOVERNOR_KEY: &str = "future_pool_governor"; + const TOTAL_WEIGHT_KEY: &str = "total_weight"; + const SHARES_DENOM_KEY: &str = "shares_denom"; + const POOL_PARAMS_KEY: &str = "pool_params"; + impl TryFrom for ValenceXykPool { type Error = StdError; fn try_from(pool: Pool) -> Result { // pack all the domain-specific fields let mut domain_specific_fields = BTreeMap::from([ - ("address".to_string(), to_json_binary(&pool.address)?), - ("id".to_string(), to_json_binary(&pool.id)?), + (ADDRESS_KEY.to_string(), to_json_binary(&pool.address)?), + (ID_KEY.to_string(), to_json_binary(&pool.id)?), ( - "future_pool_governor".to_string(), + FUTURE_POOL_GOVERNOR_KEY.to_string(), to_json_binary(&pool.future_pool_governor)?, ), ( - "total_weight".to_string(), + TOTAL_WEIGHT_KEY.to_string(), to_json_binary(&pool.total_weight)?, ), ( - "pool_params".to_string(), + POOL_PARAMS_KEY.to_string(), to_json_binary(&pool.pool_params)?, ), ]); if let Some(shares) = &pool.total_shares { domain_specific_fields - .insert("shares_denom".to_string(), to_json_binary(&shares.denom)?); + .insert(SHARES_DENOM_KEY.to_string(), to_json_binary(&shares.denom)?); } for asset in &pool.pool_assets { @@ -77,24 +84,24 @@ pub mod valence_xyk_type { fn try_from(value: ValenceXykPool) -> Result { // unpack the pool address let address: String = - try_unpack_domain_specific_value("address", &value.domain_specific_fields)?; + try_unpack_domain_specific_value(ADDRESS_KEY, &value.domain_specific_fields)?; // unpack the pool id - let id: u64 = try_unpack_domain_specific_value("id", &value.domain_specific_fields)?; + let id: u64 = try_unpack_domain_specific_value(ID_KEY, &value.domain_specific_fields)?; // unpack the future pool governor let future_pool_governor: String = try_unpack_domain_specific_value( - "future_pool_governor", + FUTURE_POOL_GOVERNOR_KEY, &value.domain_specific_fields, )?; // unpack the pool params let pool_params: Option = - try_unpack_domain_specific_value("pool_params", &value.domain_specific_fields)?; + try_unpack_domain_specific_value(POOL_PARAMS_KEY, &value.domain_specific_fields)?; // unpack the shares denom and total shares amount before combining them to a proto coin let shares_denom: String = - try_unpack_domain_specific_value("shares_denom", &value.domain_specific_fields)?; + try_unpack_domain_specific_value(SHARES_DENOM_KEY, &value.domain_specific_fields)?; let shares_coin = Coin { denom: shares_denom, amount: value.total_shares, @@ -102,7 +109,7 @@ pub mod valence_xyk_type { // unpack the total weight let total_weight: String = - try_unpack_domain_specific_value("total_weight", &value.domain_specific_fields)?; + try_unpack_domain_specific_value(TOTAL_WEIGHT_KEY, &value.domain_specific_fields)?; // unpack the pool assets let pool_assets: Vec = value @@ -149,13 +156,13 @@ pub mod valence_xyk_type { #[test] fn test_try_into() { let domain_specific_fields = BTreeMap::from([ - ("address".to_string(), to_json_binary("pool1").unwrap()), - ("id".to_string(), to_json_binary(&1).unwrap()), + (ADDRESS_KEY.to_string(), to_json_binary("pool1").unwrap()), + (ID_KEY.to_string(), to_json_binary(&1).unwrap()), ( - "future_pool_governor".to_string(), + FUTURE_POOL_GOVERNOR_KEY.to_string(), to_json_binary("gov1").unwrap(), ), - ("total_weight".to_string(), to_json_binary("100").unwrap()), + (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), ( "pool_asset_uatom_weight".to_string(), to_json_binary("120").unwrap(), @@ -165,11 +172,11 @@ pub mod valence_xyk_type { to_json_binary("80").unwrap(), ), ( - "shares_denom".to_string(), + SHARES_DENOM_KEY.to_string(), to_json_binary("osmo/gamm/whatever").unwrap(), ), ( - "pool_params".to_string(), + POOL_PARAMS_KEY.to_string(), to_json_binary(&Some(PoolParams { swap_fee: "0.003".to_string(), exit_fee: "0.0".to_string(), @@ -177,7 +184,7 @@ pub mod valence_xyk_type { })) .unwrap(), ), - ("total_weight".to_string(), to_json_binary("100").unwrap()), + (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), ]); let pool = ValenceXykPool { From ef45e9beb0bca74c741b50626a5198bfc79eee70 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 15:39:10 +0100 Subject: [PATCH 70/92] add canonical-types package; rework middleware impl --- Cargo.lock | 13 ++ Cargo.toml | 1 + .../domains/osmosis/osmo-26-0-0/Cargo.toml | 2 + .../osmosis/osmo-26-0-0/src/contract.rs | 6 +- .../domains/osmosis/osmo-26-0-0/src/lib.rs | 2 - .../domains/osmosis/osmo-26-0-0/src/msg.rs | 3 +- .../osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs | 117 ++++++++++-------- packages/canonical-types/Cargo.toml | 11 ++ .../canonical-types/src/lib.rs | 11 +- packages/canonical-types/src/pools/mod.rs | 1 + .../canonical-types/src/pools}/xyk.rs | 23 +++- packages/middleware-utils/Cargo.toml | 2 + packages/middleware-utils/src/lib.rs | 26 +++- .../middleware-utils/src/middleware_base.rs | 52 -------- 14 files changed, 144 insertions(+), 126 deletions(-) create mode 100644 packages/canonical-types/Cargo.toml rename contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs => packages/canonical-types/src/lib.rs (62%) create mode 100644 packages/canonical-types/src/pools/mod.rs rename {contracts/middleware/domains/osmosis/osmo-26-0-0/src => packages/canonical-types/src/pools}/xyk.rs (79%) delete mode 100644 packages/middleware-utils/src/middleware_base.rs diff --git a/Cargo.lock b/Cargo.lock index ee5cb17f..d3b70191 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5155,6 +5155,15 @@ dependencies = [ "valence-account-utils", ] +[[package]] +name = "valence-canonical-types" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "serde", +] + [[package]] name = "valence-forwarder-library" version = "0.1.0" @@ -5325,6 +5334,8 @@ dependencies = [ "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", + "valence-canonical-types", + "valence-middleware-utils", ] [[package]] @@ -5333,6 +5344,8 @@ version = "0.1.0" dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", + "neutron-sdk", + "valence-canonical-types", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1a1b1b3e..bccacbd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,7 @@ valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } valence-icq-lib-utils = { path = "packages/icq-querier-utils" } valence-middleware-utils = { path = "packages/middleware-utils" } +valence-canonical-types = { path = "packages/canonical-types" } # domain type registries valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml index d7864f1b..e4027012 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml @@ -26,6 +26,8 @@ serde-json-wasm = { version = "1.0.0", default-features = false } thiserror = { workspace = true } serde_json = { workspace = true } cw-storage-plus = { workspace = true } +valence-canonical-types = { workspace = true } +valence-middleware-utils = { workspace = true } [dev-dependencies] osmosis-test-tube = { workspace = true } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index d265465f..0752a119 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -5,11 +5,9 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; +use valence_canonical_types::pools::xyk::ValenceXykPool; -use crate::{ - msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, - xyk::ValenceXykPool, -}; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; // version info for migration info const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs index 21c01d66..eb320128 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs @@ -1,5 +1,3 @@ pub mod contract; -pub mod middleware; pub mod msg; pub mod osmo_gamm_pool; -pub mod xyk; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs index a8377604..0afece60 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Binary; - -use crate::xyk::ValenceXykPool; +use valence_canonical_types::pools::xyk::ValenceXykPool; #[cw_serde] pub struct InstantiateMsg {} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs index 1460e676..70055e03 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs @@ -1,13 +1,19 @@ +use osmosis_std::types::osmosis::gamm::v1beta1::Pool; +pub struct OsmosisXykPool(pub Pool); + pub mod valence_xyk_type { use std::collections::BTreeMap; use std::str::FromStr; - use crate::{middleware::try_unpack_domain_specific_value, xyk::ValenceXykPool}; - use cosmwasm_std::to_json_binary; - use cosmwasm_std::{StdError, Uint128}; - use osmosis_std::types::osmosis::gamm::v1beta1::Pool; - use osmosis_std::types::osmosis::gamm::v1beta1::PoolParams; + use cosmwasm_std::Uint128; + use cosmwasm_std::{to_json_binary, StdResult}; + + use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; + use valence_canonical_types::pools::xyk::{ValenceXykAdapter, ValenceXykPool}; + use valence_canonical_types::try_unpack_domain_specific_value; + + use super::OsmosisXykPool; const ADDRESS_KEY: &str = "address"; const ID_KEY: &str = "id"; @@ -16,34 +22,34 @@ pub mod valence_xyk_type { const SHARES_DENOM_KEY: &str = "shares_denom"; const POOL_PARAMS_KEY: &str = "pool_params"; - impl TryFrom for ValenceXykPool { - type Error = StdError; + impl ValenceXykAdapter for OsmosisXykPool { + type External = Pool; - fn try_from(pool: Pool) -> Result { + fn try_to_canonical(&self) -> StdResult { // pack all the domain-specific fields let mut domain_specific_fields = BTreeMap::from([ - (ADDRESS_KEY.to_string(), to_json_binary(&pool.address)?), - (ID_KEY.to_string(), to_json_binary(&pool.id)?), + (ADDRESS_KEY.to_string(), to_json_binary(&self.0.address)?), + (ID_KEY.to_string(), to_json_binary(&self.0.id)?), ( FUTURE_POOL_GOVERNOR_KEY.to_string(), - to_json_binary(&pool.future_pool_governor)?, + to_json_binary(&self.0.future_pool_governor)?, ), ( TOTAL_WEIGHT_KEY.to_string(), - to_json_binary(&pool.total_weight)?, + to_json_binary(&self.0.total_weight)?, ), ( POOL_PARAMS_KEY.to_string(), - to_json_binary(&pool.pool_params)?, + to_json_binary(&self.0.pool_params)?, ), ]); - if let Some(shares) = &pool.total_shares { + if let Some(shares) = &self.0.total_shares { domain_specific_fields .insert(SHARES_DENOM_KEY.to_string(), to_json_binary(&shares.denom)?); } - for asset in &pool.pool_assets { + for asset in &self.0.pool_assets { if let Some(token) = &asset.token { domain_specific_fields.insert( format!("pool_asset_{}_weight", token.denom), @@ -52,8 +58,10 @@ pub mod valence_xyk_type { } } - let assets = pool + let assets = self + .0 .pool_assets + .clone() .into_iter() .filter_map(|asset| { asset.token.map(|token| { @@ -65,8 +73,10 @@ pub mod valence_xyk_type { }) .collect(); - let total_shares = pool + let total_shares = self + .0 .total_shares + .clone() .map(|shares| shares.amount) .unwrap_or_default(); @@ -76,43 +86,46 @@ pub mod valence_xyk_type { domain_specific_fields, }) } - } - - impl TryFrom for Pool { - type Error = StdError; - fn try_from(value: ValenceXykPool) -> Result { + fn try_from_canonical(canonical: ValenceXykPool) -> StdResult { // unpack the pool address let address: String = - try_unpack_domain_specific_value(ADDRESS_KEY, &value.domain_specific_fields)?; + try_unpack_domain_specific_value(ADDRESS_KEY, &canonical.domain_specific_fields)?; // unpack the pool id - let id: u64 = try_unpack_domain_specific_value(ID_KEY, &value.domain_specific_fields)?; + let id: u64 = + try_unpack_domain_specific_value(ID_KEY, &canonical.domain_specific_fields)?; // unpack the future pool governor let future_pool_governor: String = try_unpack_domain_specific_value( FUTURE_POOL_GOVERNOR_KEY, - &value.domain_specific_fields, + &canonical.domain_specific_fields, )?; // unpack the pool params - let pool_params: Option = - try_unpack_domain_specific_value(POOL_PARAMS_KEY, &value.domain_specific_fields)?; + let pool_params: Option = try_unpack_domain_specific_value( + POOL_PARAMS_KEY, + &canonical.domain_specific_fields, + )?; // unpack the shares denom and total shares amount before combining them to a proto coin - let shares_denom: String = - try_unpack_domain_specific_value(SHARES_DENOM_KEY, &value.domain_specific_fields)?; + let shares_denom: String = try_unpack_domain_specific_value( + SHARES_DENOM_KEY, + &canonical.domain_specific_fields, + )?; let shares_coin = Coin { denom: shares_denom, - amount: value.total_shares, + amount: canonical.total_shares, }; // unpack the total weight - let total_weight: String = - try_unpack_domain_specific_value(TOTAL_WEIGHT_KEY, &value.domain_specific_fields)?; + let total_weight: String = try_unpack_domain_specific_value( + TOTAL_WEIGHT_KEY, + &canonical.domain_specific_fields, + )?; // unpack the pool assets - let pool_assets: Vec = value + let pool_assets: Vec = canonical .assets .iter() .map(|asset| { @@ -123,7 +136,7 @@ pub mod valence_xyk_type { let weight: String = try_unpack_domain_specific_value( &format!("pool_asset_{}_weight", asset.denom), - &value.domain_specific_fields, + &canonical.domain_specific_fields, ) .unwrap(); @@ -150,7 +163,6 @@ pub mod valence_xyk_type { mod tests { use super::*; use cosmwasm_std::{coin, to_json_binary}; - use osmosis_std::types::osmosis::gamm::v1beta1::Pool; use std::collections::BTreeMap; #[test] @@ -193,7 +205,7 @@ pub mod valence_xyk_type { domain_specific_fields, }; - let osmosis_pool: Pool = pool.try_into().unwrap(); + let osmosis_pool = OsmosisXykPool::try_from_canonical(pool).unwrap(); println!("osmosis_pool: {:?}", osmosis_pool); assert_eq!(osmosis_pool.address, "pool1"); @@ -243,8 +255,7 @@ pub mod valence_xyk_type { total_weight: "100".to_string(), }; - let valence_xyk_pool = ValenceXykPool::try_from(pool).unwrap(); - + let valence_xyk_pool = OsmosisXykPool(pool).try_to_canonical().unwrap(); println!("parsed xyk pool: {:?}", valence_xyk_pool); assert_eq!(valence_xyk_pool.assets.len(), 2); @@ -261,19 +272,14 @@ pub mod icq { use cosmwasm_std::{to_json_binary, Binary, StdError, StdResult}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; + use valence_canonical_types::try_unpack_domain_specific_value; + use valence_middleware_utils::IcqIntegration; - use crate::middleware::try_unpack_domain_specific_value; use prost::Message; - pub trait IcqIntegration { - fn get_kv_key(&self, params: BTreeMap) -> StdResult; - fn decode_and_reconstruct( - query_id: String, - icq_result: InterchainQueryResult, - ) -> StdResult; - } + use super::OsmosisXykPool; - impl IcqIntegration for Pool { + impl IcqIntegration for OsmosisXykPool { fn get_kv_key(&self, params: BTreeMap) -> StdResult { let pool_prefix_key: u8 = 0x02; @@ -316,7 +322,7 @@ pub mod icq { let mut params = BTreeMap::new(); params.insert("pool_id".to_string(), to_json_binary(&1u64).unwrap()); - let kv_key = pool.get_kv_key(params).unwrap(); + let kv_key = OsmosisXykPool(pool).get_kv_key(params).unwrap(); let b64_key = "AgAAAAAAAAAB"; let binary_key = Binary::from_base64(b64_key).unwrap(); @@ -339,7 +345,7 @@ pub mod icq { value: binary_value, }; - let osmo_pool_binary = Pool::decode_and_reconstruct( + let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( Pool::TYPE_URL.to_string(), InterchainQueryResult { kv_results: vec![storage_value], @@ -405,10 +411,10 @@ mod tests { use cosmwasm_std::{from_json, Binary}; use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + use valence_canonical_types::pools::xyk::ValenceXykAdapter; + use valence_middleware_utils::IcqIntegration; - use crate::xyk::ValenceXykPool; - - use super::icq::IcqIntegration; + use crate::osmo_gamm_pool::OsmosisXykPool; #[test] fn e2e() { @@ -425,7 +431,7 @@ mod tests { }; // first we simulate the icq result reconstruction of b64(proto) -> type -> b64(type) - let osmo_pool_binary = Pool::decode_and_reconstruct( + let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( Pool::TYPE_URL.to_string(), InterchainQueryResult { kv_results: vec![storage_value], @@ -439,7 +445,8 @@ mod tests { let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); // parse the external type into a valence type - let mut valence_pool: ValenceXykPool = osmo_pool.try_into().unwrap(); + + let mut valence_pool = OsmosisXykPool(osmo_pool).try_to_canonical().unwrap(); // simulate modifying the pool instance valence_pool.assets.push(cosmwasm_std::coin(100, "batom")); @@ -449,7 +456,7 @@ mod tests { ); // convert the valence type back into the external type - let osmo_pool: Pool = valence_pool.try_into().unwrap(); + let osmo_pool = OsmosisXykPool::try_from_canonical(valence_pool).unwrap(); assert_eq!(osmo_pool.pool_assets.len(), 3); } diff --git a/packages/canonical-types/Cargo.toml b/packages/canonical-types/Cargo.toml new file mode 100644 index 00000000..bfea9699 --- /dev/null +++ b/packages/canonical-types/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "valence-canonical-types" +version = { workspace = true } +edition = { workspace = true } +authors = { workspace = true } +description = "canonical types for Valence Protocol" + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +serde = { workspace = true } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs b/packages/canonical-types/src/lib.rs similarity index 62% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs rename to packages/canonical-types/src/lib.rs index 72a83742..20066e31 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/middleware.rs +++ b/packages/canonical-types/src/lib.rs @@ -1,16 +1,9 @@ use std::collections::BTreeMap; -use cosmwasm_schema::serde::de::DeserializeOwned; use cosmwasm_std::{from_json, StdError, StdResult}; +use serde::de::DeserializeOwned; -// fn process_pool>(external_pool: T) { -// // let valence_pool = external_pool.to_valence_xyk_pool(); -// } - -// trait ValenceMiddlewareTypeDefinition { -// fn serialize(&self) -> Binary; -// fn deserialize(&self) -> Self; -// } +pub mod pools; pub fn try_unpack_domain_specific_value( key: &str, diff --git a/packages/canonical-types/src/pools/mod.rs b/packages/canonical-types/src/pools/mod.rs new file mode 100644 index 00000000..4f7ecb40 --- /dev/null +++ b/packages/canonical-types/src/pools/mod.rs @@ -0,0 +1 @@ +pub mod xyk; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs b/packages/canonical-types/src/pools/xyk.rs similarity index 79% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs rename to packages/canonical-types/src/pools/xyk.rs index 13181391..1196fd8c 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/xyk.rs +++ b/packages/canonical-types/src/pools/xyk.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Binary, Coin}; +use cosmwasm_std::{ensure, Binary, Coin, Decimal, StdError, StdResult}; #[cw_serde] pub struct ValenceXykPool { @@ -14,6 +14,27 @@ pub struct ValenceXykPool { pub domain_specific_fields: BTreeMap, } +impl ValenceXykPool { + pub fn get_price(&self) -> StdResult { + ensure!( + self.assets.len() == 2, + StdError::generic_err("price can be calculated iff xyk pool contains exactly 2 assets") + ); + + let a = self.assets[0].amount; + let b = self.assets[1].amount; + + Ok(Decimal::from_ratio(a, b)) + } +} + +pub trait ValenceXykAdapter { + type External; + + fn try_to_canonical(&self) -> StdResult; + fn try_from_canonical(canonical: ValenceXykPool) -> StdResult; +} + /* OSMOSIS POOL diff --git a/packages/middleware-utils/Cargo.toml b/packages/middleware-utils/Cargo.toml index aad666e8..7d55b1d5 100644 --- a/packages/middleware-utils/Cargo.toml +++ b/packages/middleware-utils/Cargo.toml @@ -8,3 +8,5 @@ description = "valence middleware utilities" [dependencies] cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } +valence-canonical-types = { workspace = true } +neutron-sdk = { workspace = true } diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index fd2ec330..9d6b3de0 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -1 +1,25 @@ -pub mod middleware_base; +use std::collections::BTreeMap; + +use cosmwasm_std::{Binary, StdResult}; +use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; +// use valence_canonical_types::pools::xyk::ValenceXykPool; + +// pub trait ValenceTypeAdapter { +// type External; + +// fn to_canonical(&self) -> StdResult; +// fn from_canonical(canonical: ValenceXykPool) -> StdResult; +// } + +pub trait MiddlewareSerializer: Sized { + fn serialize(&self) -> StdResult; + fn deserialize(binary: Binary) -> StdResult; +} + +pub trait IcqIntegration { + fn get_kv_key(&self, params: BTreeMap) -> StdResult; + fn decode_and_reconstruct( + query_id: String, + icq_result: InterchainQueryResult, + ) -> StdResult; +} diff --git a/packages/middleware-utils/src/middleware_base.rs b/packages/middleware-utils/src/middleware_base.rs deleted file mode 100644 index 27d5e122..00000000 --- a/packages/middleware-utils/src/middleware_base.rs +++ /dev/null @@ -1,52 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Binary, CosmosMsg, Empty, SubMsgResponse, Uint64}; - -#[cw_serde] -pub enum PolytoneExecuteMsg { - Execute { - msgs: Vec>, - callback: Option, - timeout_seconds: Uint64, - }, -} - -#[cw_serde] -pub struct CallbackRequest { - pub receiver: String, - pub msg: Binary, -} - -#[cw_serde] -pub struct CallbackMessage { - /// Initaitor on the note chain. - pub initiator: Addr, - /// Message sent by the initaitor. This _must_ be base64 encoded - /// or execution will fail. - pub initiator_msg: Binary, - /// Data from the host chain. - pub result: Callback, -} - -#[cw_serde] -pub enum Callback { - Query(Result, ErrorResponse>), - Execute(Result), - FatalError(String), -} - -#[cw_serde] -pub struct ExecutionResponse { - /// The address on the remote chain that executed the messages. - pub executed_by: String, - /// Index `i` corresponds to the result of executing the `i`th - /// message. - pub result: Vec, -} - -#[cw_serde] -pub struct ErrorResponse { - /// The index of the first message who's execution failed. - pub message_index: Uint64, - /// The error that occured executing the message. - pub error: String, -} From 31fd78da44ba0fde50022446bbad1482a861cbb3 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 17:00:48 +0100 Subject: [PATCH 71/92] merge packages into middleware-utils --- Cargo.lock | 12 +- Cargo.toml | 2 +- .../domains/osmosis/osmo-26-0-0/Cargo.toml | 2 +- .../osmosis/osmo-26-0-0/src/contract.rs | 2 +- .../definitions/gamm_pool/domain_adapter.rs | 139 ++++++ .../src/definitions/gamm_pool/mod.rs | 71 +++ .../definitions/gamm_pool/valence_adapter.rs | 239 +++++++++ .../osmo-26-0-0/src/definitions/mod.rs | 1 + .../domains/osmosis/osmo-26-0-0/src/lib.rs | 2 +- .../domains/osmosis/osmo-26-0-0/src/msg.rs | 2 +- .../osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs | 463 ------------------ packages/canonical-types/Cargo.toml | 11 - packages/canonical-types/src/lib.rs | 24 - packages/middleware-utils/Cargo.toml | 3 +- .../src/canonical_types/mod.rs | 1 + .../src/canonical_types}/pools/mod.rs | 0 .../src/canonical_types}/pools/xyk.rs | 6 +- packages/middleware-utils/src/lib.rs | 47 +- 18 files changed, 495 insertions(+), 532 deletions(-) create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs delete mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs delete mode 100644 packages/canonical-types/Cargo.toml delete mode 100644 packages/canonical-types/src/lib.rs create mode 100644 packages/middleware-utils/src/canonical_types/mod.rs rename packages/{canonical-types/src => middleware-utils/src/canonical_types}/pools/mod.rs (100%) rename packages/{canonical-types/src => middleware-utils/src/canonical_types}/pools/xyk.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index d3b70191..83818452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5155,15 +5155,6 @@ dependencies = [ "valence-account-utils", ] -[[package]] -name = "valence-canonical-types" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema 2.1.4", - "cosmwasm-std 2.1.4", - "serde", -] - [[package]] name = "valence-forwarder-library" version = "0.1.0" @@ -5334,7 +5325,6 @@ dependencies = [ "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", - "valence-canonical-types", "valence-middleware-utils", ] @@ -5345,7 +5335,7 @@ dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "neutron-sdk", - "valence-canonical-types", + "thiserror 1.0.69", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bccacbd5..4583a4e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } valence-icq-lib-utils = { path = "packages/icq-querier-utils" } valence-middleware-utils = { path = "packages/middleware-utils" } -valence-canonical-types = { path = "packages/canonical-types" } +# valence-canonical-types = { path = "packages/canonical-types" } # domain type registries valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml index e4027012..4ced8c44 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml @@ -26,7 +26,7 @@ serde-json-wasm = { version = "1.0.0", default-features = false } thiserror = { workspace = true } serde_json = { workspace = true } cw-storage-plus = { workspace = true } -valence-canonical-types = { workspace = true } +# valence-canonical-types = { workspace = true } valence-middleware-utils = { workspace = true } [dev-dependencies] diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 0752a119..9dd94e67 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -5,7 +5,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; -use valence_canonical_types::pools::xyk::ValenceXykPool; +use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs new file mode 100644 index 00000000..68277044 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs @@ -0,0 +1,139 @@ +use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + +use std::collections::BTreeMap; + +use cosmwasm_std::{to_json_binary, Binary, StdError}; +use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; +use osmosis_std::shim::Any; +use valence_middleware_utils::{try_unpack_domain_specific_value, IcqIntegration, MiddlewareError}; + +use prost::Message; + +use super::{OsmosisXykPool, STORAGE_PREFIX}; + +impl IcqIntegration for OsmosisXykPool { + fn get_kv_key(&self, params: BTreeMap) -> Result { + let pool_prefix_key: u8 = 0x02; + + let id: u64 = try_unpack_domain_specific_value("pool_id", ¶ms)?; + + let mut pool_access_key = vec![pool_prefix_key]; + pool_access_key.extend_from_slice(&id.to_be_bytes()); + + Ok(KVKey { + path: STORAGE_PREFIX.to_string(), + key: Binary::new(pool_access_key), + }) + } + + fn decode_and_reconstruct( + query_id: String, + icq_result: InterchainQueryResult, + ) -> Result { + let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice()) + .map_err(|e| StdError::generic_err(e.to_string()))?; + + let osmo_pool: Pool = any_msg + .try_into() + .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; + + let binary = to_json_binary(&osmo_pool)?; + + Ok(binary) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::{from_json, to_json_binary, Binary}; + use neutron_sdk::bindings::types::StorageValue; + use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolAsset, PoolParams}; + + #[test] + fn test_get_kv_key() { + let pool = Pool::default(); + let mut params = BTreeMap::new(); + params.insert("pool_id".to_string(), to_json_binary(&1u64).unwrap()); + + let kv_key = OsmosisXykPool(pool).get_kv_key(params).unwrap(); + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + assert_eq!(kv_key.path, "gamm"); + assert_eq!(kv_key.key, Binary::new(vec![2, 0, 0, 0, 0, 0, 0, 0, 1])); + assert_eq!(kv_key.key, binary_key); + } + + #[test] + fn test_decode_and_reconstruct() { + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "gamm".to_string(), + key: binary_key, + value: binary_value, + }; + + let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( + Pool::TYPE_URL.to_string(), + InterchainQueryResult { + kv_results: vec![storage_value], + height: 1, + revision: 1, + }, + ) + .unwrap(); + + let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); + + assert_eq!( + osmo_pool.address, + "osmo19e2mf7cywkv7zaug6nk5f87d07fxrdgrladvymh2gwv5crvm3vnsuewhh7".to_string() + ); + assert_eq!(osmo_pool.id, 1); + assert_eq!( + osmo_pool.pool_params, + Some(PoolParams { + swap_fee: "0".to_string(), + exit_fee: "0".to_string(), + smooth_weight_change_params: None + }) + ); + assert_eq!(osmo_pool.future_pool_governor, "128h".to_string()); + assert_eq!( + osmo_pool.total_shares, + Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: "gamm/pool/1".to_string(), + amount: "100000000000000000000".to_string() + }) + ); + assert_eq!(osmo_pool.pool_assets.len(), 2); + assert_eq!( + osmo_pool.pool_assets[0], + PoolAsset { + token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: "ibc/4E41ED8F3DCAEA15F4D6ADC6EDD7C04A676160735C9710B904B7BF53525B56D6" + .to_string(), + amount: "100000000".to_string() + }), + weight: "1073741824".to_string() + } + ); + assert_eq!( + osmo_pool.pool_assets[1], + PoolAsset { + token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { + denom: "uosmo".to_string(), + amount: "100000000".to_string() + }), + weight: "1073741824".to_string() + } + ); + assert_eq!(osmo_pool.total_weight, "2147483648"); + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs new file mode 100644 index 00000000..0fc30ecf --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs @@ -0,0 +1,71 @@ +use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + +pub mod domain_adapter; +pub mod valence_adapter; + +const ADDRESS_KEY: &str = "address"; +const ID_KEY: &str = "id"; +const FUTURE_POOL_GOVERNOR_KEY: &str = "future_pool_governor"; +const TOTAL_WEIGHT_KEY: &str = "total_weight"; +const SHARES_DENOM_KEY: &str = "shares_denom"; +const POOL_PARAMS_KEY: &str = "pool_params"; +const STORAGE_PREFIX: &str = "gamm"; + +pub struct OsmosisXykPool(pub Pool); + +#[cfg(test)] +mod tests { + use cosmwasm_std::{from_json, Binary}; + use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; + use osmosis_std::types::osmosis::gamm::v1beta1::Pool; + use valence_middleware_utils::{ + canonical_types::pools::xyk::ValenceXykAdapter, IcqIntegration, + }; + + use crate::definitions::gamm_pool::{OsmosisXykPool, STORAGE_PREFIX}; + + #[test] + fn e2e() { + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: STORAGE_PREFIX.to_string(), + key: binary_key, + value: binary_value, + }; + + // first we simulate the icq result reconstruction of b64(proto) -> type -> b64(type) + let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( + Pool::TYPE_URL.to_string(), + InterchainQueryResult { + kv_results: vec![storage_value], + height: 1, + revision: 1, + }, + ) + .unwrap(); + + // unpack the binary into a type + let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); + + // parse the external type into a valence type + + let mut valence_pool = OsmosisXykPool(osmo_pool).try_to_canonical().unwrap(); + + // simulate modifying the pool instance + valence_pool.assets.push(cosmwasm_std::coin(100, "batom")); + valence_pool.domain_specific_fields.insert( + "pool_asset_batom_weight".to_string(), + cosmwasm_std::to_json_binary(&"120").unwrap(), + ); + + // convert the valence type back into the external type + let osmo_pool = OsmosisXykPool::try_from_canonical(valence_pool).unwrap(); + + assert_eq!(osmo_pool.pool_assets.len(), 3); + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs new file mode 100644 index 00000000..164aa28b --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs @@ -0,0 +1,239 @@ +use std::collections::BTreeMap; +use std::str::FromStr; + +use cosmwasm_std::to_json_binary; +use cosmwasm_std::{coin, StdError}; + +use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; +use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; +use valence_middleware_utils::canonical_types::pools::xyk::{ValenceXykAdapter, ValenceXykPool}; +use valence_middleware_utils::{try_unpack_domain_specific_value, MiddlewareError}; + +use super::{ + OsmosisXykPool, ADDRESS_KEY, FUTURE_POOL_GOVERNOR_KEY, ID_KEY, POOL_PARAMS_KEY, + SHARES_DENOM_KEY, TOTAL_WEIGHT_KEY, +}; + +impl ValenceXykAdapter for OsmosisXykPool { + type External = Pool; + + fn try_to_canonical(&self) -> Result { + // pack all the domain-specific fields + let mut domain_specific_fields = BTreeMap::from([ + (ADDRESS_KEY.to_string(), to_json_binary(&self.0.address)?), + (ID_KEY.to_string(), to_json_binary(&self.0.id)?), + ( + FUTURE_POOL_GOVERNOR_KEY.to_string(), + to_json_binary(&self.0.future_pool_governor)?, + ), + ( + TOTAL_WEIGHT_KEY.to_string(), + to_json_binary(&self.0.total_weight)?, + ), + ( + POOL_PARAMS_KEY.to_string(), + to_json_binary(&self.0.pool_params)?, + ), + ]); + + if let Some(shares) = &self.0.total_shares { + domain_specific_fields + .insert(SHARES_DENOM_KEY.to_string(), to_json_binary(&shares.denom)?); + } + + for asset in &self.0.pool_assets { + if let Some(token) = &asset.token { + domain_specific_fields.insert( + format!("pool_asset_{}_weight", token.denom), + to_json_binary(&asset.weight)?, + ); + } + } + + let mut assets = vec![]; + for asset in &self.0.pool_assets { + if let Some(t) = &asset.token { + assets.push(coin( + u128::from_str(&t.amount).map_err(|e| StdError::generic_err(e.to_string()))?, + t.denom.to_string(), + )); + } + } + + let total_shares = self + .0 + .total_shares + .clone() + .map(|shares| shares.amount) + .unwrap_or_default(); + + Ok(ValenceXykPool { + assets, + total_shares, + domain_specific_fields, + }) + } + + fn try_from_canonical(canonical: ValenceXykPool) -> Result { + // unpack the pool address + let address: String = + try_unpack_domain_specific_value(ADDRESS_KEY, &canonical.domain_specific_fields)?; + + // unpack the pool id + let id: u64 = try_unpack_domain_specific_value(ID_KEY, &canonical.domain_specific_fields)?; + + // unpack the future pool governor + let future_pool_governor: String = try_unpack_domain_specific_value( + FUTURE_POOL_GOVERNOR_KEY, + &canonical.domain_specific_fields, + )?; + + // unpack the pool params + let pool_params: Option = + try_unpack_domain_specific_value(POOL_PARAMS_KEY, &canonical.domain_specific_fields)?; + + // unpack the shares denom and total shares amount before combining them to a proto coin + let shares_denom: String = + try_unpack_domain_specific_value(SHARES_DENOM_KEY, &canonical.domain_specific_fields)?; + let shares_coin = Coin { + denom: shares_denom, + amount: canonical.total_shares, + }; + + // unpack the total weight + let total_weight: String = + try_unpack_domain_specific_value(TOTAL_WEIGHT_KEY, &canonical.domain_specific_fields)?; + + // unpack the pool assets + let mut pool_assets = vec![]; + for asset in &canonical.assets { + let pool_asset = PoolAsset { + token: Some(Coin { + denom: asset.denom.to_string(), + amount: asset.amount.into(), + }), + weight: try_unpack_domain_specific_value( + &format!("pool_asset_{}_weight", asset.denom), + &canonical.domain_specific_fields, + )?, + }; + pool_assets.push(pool_asset); + } + + Ok(Pool { + address, + id, + pool_params, + future_pool_governor, + total_shares: Some(shares_coin), + pool_assets, + total_weight, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::{coin, to_json_binary}; + use std::collections::BTreeMap; + + #[test] + fn test_try_into() { + let domain_specific_fields = BTreeMap::from([ + (ADDRESS_KEY.to_string(), to_json_binary("pool1").unwrap()), + (ID_KEY.to_string(), to_json_binary(&1).unwrap()), + ( + FUTURE_POOL_GOVERNOR_KEY.to_string(), + to_json_binary("gov1").unwrap(), + ), + (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), + ( + "pool_asset_uatom_weight".to_string(), + to_json_binary("120").unwrap(), + ), + ( + "pool_asset_uosmo_weight".to_string(), + to_json_binary("80").unwrap(), + ), + ( + SHARES_DENOM_KEY.to_string(), + to_json_binary("osmo/gamm/whatever").unwrap(), + ), + ( + POOL_PARAMS_KEY.to_string(), + to_json_binary(&Some(PoolParams { + swap_fee: "0.003".to_string(), + exit_fee: "0.0".to_string(), + smooth_weight_change_params: None, + })) + .unwrap(), + ), + (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), + ]); + + let pool = ValenceXykPool { + assets: vec![coin(100, "uatom"), coin(200, "uosmo")], + total_shares: "1000".to_string(), + domain_specific_fields, + }; + + let osmosis_pool = OsmosisXykPool::try_from_canonical(pool).unwrap(); + + println!("osmosis_pool: {:?}", osmosis_pool); + assert_eq!(osmosis_pool.address, "pool1"); + assert_eq!(osmosis_pool.id, 1); + assert_eq!(osmosis_pool.future_pool_governor, "gov1"); + assert_eq!(osmosis_pool.total_weight, "100"); + assert_eq!(osmosis_pool.pool_assets.len(), 2); + assert_eq!(osmosis_pool.pool_assets[0].weight, "120"); + assert_eq!(osmosis_pool.pool_assets[1].weight, "80"); + let total_shares = osmosis_pool.total_shares.unwrap(); + assert_eq!(total_shares.amount, "1000"); + assert_eq!(total_shares.denom, "osmo/gamm/whatever"); + assert_eq!(osmosis_pool.pool_params.unwrap().swap_fee, "0.003"); + } + + #[test] + fn test_try_from() { + let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool { + address: "pool1".to_string(), + id: 1, + pool_params: Some(PoolParams { + swap_fee: "0.003".to_string(), + exit_fee: "0.0".to_string(), + smooth_weight_change_params: None, + }), + future_pool_governor: "gov1".to_string(), + total_shares: Some(Coin { + denom: "osmo/gamm/whatever".to_string(), + amount: "1000".to_string(), + }), + pool_assets: vec![ + PoolAsset { + token: Some(Coin { + denom: "uatom".to_string(), + amount: "100".to_string(), + }), + weight: "120".to_string(), + }, + PoolAsset { + token: Some(Coin { + denom: "uosmo".to_string(), + amount: "200".to_string(), + }), + weight: "80".to_string(), + }, + ], + total_weight: "100".to_string(), + }; + + let valence_xyk_pool = OsmosisXykPool(pool).try_to_canonical().unwrap(); + println!("parsed xyk pool: {:?}", valence_xyk_pool); + + assert_eq!(valence_xyk_pool.assets.len(), 2); + assert_eq!(valence_xyk_pool.assets[0], coin(100, "uatom")); + assert_eq!(valence_xyk_pool.assets[1], coin(200, "uosmo")); + assert_eq!(valence_xyk_pool.total_shares, "1000"); + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs new file mode 100644 index 00000000..a4f13977 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -0,0 +1 @@ +pub mod gamm_pool; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs index eb320128..8a72c442 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs @@ -1,3 +1,3 @@ pub mod contract; +pub mod definitions; pub mod msg; -pub mod osmo_gamm_pool; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs index 0afece60..35effc5a 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Binary; -use valence_canonical_types::pools::xyk::ValenceXykPool; +use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; #[cw_serde] pub struct InstantiateMsg {} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs deleted file mode 100644 index 70055e03..00000000 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/osmo_gamm_pool.rs +++ /dev/null @@ -1,463 +0,0 @@ -use osmosis_std::types::osmosis::gamm::v1beta1::Pool; -pub struct OsmosisXykPool(pub Pool); - -pub mod valence_xyk_type { - use std::collections::BTreeMap; - use std::str::FromStr; - - use cosmwasm_std::Uint128; - use cosmwasm_std::{to_json_binary, StdResult}; - - use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; - use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; - use valence_canonical_types::pools::xyk::{ValenceXykAdapter, ValenceXykPool}; - use valence_canonical_types::try_unpack_domain_specific_value; - - use super::OsmosisXykPool; - - const ADDRESS_KEY: &str = "address"; - const ID_KEY: &str = "id"; - const FUTURE_POOL_GOVERNOR_KEY: &str = "future_pool_governor"; - const TOTAL_WEIGHT_KEY: &str = "total_weight"; - const SHARES_DENOM_KEY: &str = "shares_denom"; - const POOL_PARAMS_KEY: &str = "pool_params"; - - impl ValenceXykAdapter for OsmosisXykPool { - type External = Pool; - - fn try_to_canonical(&self) -> StdResult { - // pack all the domain-specific fields - let mut domain_specific_fields = BTreeMap::from([ - (ADDRESS_KEY.to_string(), to_json_binary(&self.0.address)?), - (ID_KEY.to_string(), to_json_binary(&self.0.id)?), - ( - FUTURE_POOL_GOVERNOR_KEY.to_string(), - to_json_binary(&self.0.future_pool_governor)?, - ), - ( - TOTAL_WEIGHT_KEY.to_string(), - to_json_binary(&self.0.total_weight)?, - ), - ( - POOL_PARAMS_KEY.to_string(), - to_json_binary(&self.0.pool_params)?, - ), - ]); - - if let Some(shares) = &self.0.total_shares { - domain_specific_fields - .insert(SHARES_DENOM_KEY.to_string(), to_json_binary(&shares.denom)?); - } - - for asset in &self.0.pool_assets { - if let Some(token) = &asset.token { - domain_specific_fields.insert( - format!("pool_asset_{}_weight", token.denom), - to_json_binary(&asset.weight)?, - ); - } - } - - let assets = self - .0 - .pool_assets - .clone() - .into_iter() - .filter_map(|asset| { - asset.token.map(|token| { - cosmwasm_std::coin( - Uint128::from_str(&token.amount).unwrap().into(), - token.denom, - ) - }) - }) - .collect(); - - let total_shares = self - .0 - .total_shares - .clone() - .map(|shares| shares.amount) - .unwrap_or_default(); - - Ok(ValenceXykPool { - assets, - total_shares, - domain_specific_fields, - }) - } - - fn try_from_canonical(canonical: ValenceXykPool) -> StdResult { - // unpack the pool address - let address: String = - try_unpack_domain_specific_value(ADDRESS_KEY, &canonical.domain_specific_fields)?; - - // unpack the pool id - let id: u64 = - try_unpack_domain_specific_value(ID_KEY, &canonical.domain_specific_fields)?; - - // unpack the future pool governor - let future_pool_governor: String = try_unpack_domain_specific_value( - FUTURE_POOL_GOVERNOR_KEY, - &canonical.domain_specific_fields, - )?; - - // unpack the pool params - let pool_params: Option = try_unpack_domain_specific_value( - POOL_PARAMS_KEY, - &canonical.domain_specific_fields, - )?; - - // unpack the shares denom and total shares amount before combining them to a proto coin - let shares_denom: String = try_unpack_domain_specific_value( - SHARES_DENOM_KEY, - &canonical.domain_specific_fields, - )?; - let shares_coin = Coin { - denom: shares_denom, - amount: canonical.total_shares, - }; - - // unpack the total weight - let total_weight: String = try_unpack_domain_specific_value( - TOTAL_WEIGHT_KEY, - &canonical.domain_specific_fields, - )?; - - // unpack the pool assets - let pool_assets: Vec = canonical - .assets - .iter() - .map(|asset| { - let coin = Coin { - denom: asset.denom.to_string(), - amount: asset.amount.into(), - }; - - let weight: String = try_unpack_domain_specific_value( - &format!("pool_asset_{}_weight", asset.denom), - &canonical.domain_specific_fields, - ) - .unwrap(); - - PoolAsset { - token: Some(coin), - weight, - } - }) - .collect(); - - Ok(Pool { - address, - id, - pool_params, - future_pool_governor, - total_shares: Some(shares_coin), - pool_assets, - total_weight, - }) - } - } - - #[cfg(test)] - mod tests { - use super::*; - use cosmwasm_std::{coin, to_json_binary}; - use std::collections::BTreeMap; - - #[test] - fn test_try_into() { - let domain_specific_fields = BTreeMap::from([ - (ADDRESS_KEY.to_string(), to_json_binary("pool1").unwrap()), - (ID_KEY.to_string(), to_json_binary(&1).unwrap()), - ( - FUTURE_POOL_GOVERNOR_KEY.to_string(), - to_json_binary("gov1").unwrap(), - ), - (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), - ( - "pool_asset_uatom_weight".to_string(), - to_json_binary("120").unwrap(), - ), - ( - "pool_asset_uosmo_weight".to_string(), - to_json_binary("80").unwrap(), - ), - ( - SHARES_DENOM_KEY.to_string(), - to_json_binary("osmo/gamm/whatever").unwrap(), - ), - ( - POOL_PARAMS_KEY.to_string(), - to_json_binary(&Some(PoolParams { - swap_fee: "0.003".to_string(), - exit_fee: "0.0".to_string(), - smooth_weight_change_params: None, - })) - .unwrap(), - ), - (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), - ]); - - let pool = ValenceXykPool { - assets: vec![coin(100, "uatom"), coin(200, "uosmo")], - total_shares: "1000".to_string(), - domain_specific_fields, - }; - - let osmosis_pool = OsmosisXykPool::try_from_canonical(pool).unwrap(); - - println!("osmosis_pool: {:?}", osmosis_pool); - assert_eq!(osmosis_pool.address, "pool1"); - assert_eq!(osmosis_pool.id, 1); - assert_eq!(osmosis_pool.future_pool_governor, "gov1"); - assert_eq!(osmosis_pool.total_weight, "100"); - assert_eq!(osmosis_pool.pool_assets.len(), 2); - assert_eq!(osmosis_pool.pool_assets[0].weight, "120"); - assert_eq!(osmosis_pool.pool_assets[1].weight, "80"); - let total_shares = osmosis_pool.total_shares.unwrap(); - assert_eq!(total_shares.amount, "1000"); - assert_eq!(total_shares.denom, "osmo/gamm/whatever"); - assert_eq!(osmosis_pool.pool_params.unwrap().swap_fee, "0.003"); - } - - #[test] - fn test_try_from() { - let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool { - address: "pool1".to_string(), - id: 1, - pool_params: Some(PoolParams { - swap_fee: "0.003".to_string(), - exit_fee: "0.0".to_string(), - smooth_weight_change_params: None, - }), - future_pool_governor: "gov1".to_string(), - total_shares: Some(Coin { - denom: "osmo/gamm/whatever".to_string(), - amount: "1000".to_string(), - }), - pool_assets: vec![ - PoolAsset { - token: Some(Coin { - denom: "uatom".to_string(), - amount: "100".to_string(), - }), - weight: "120".to_string(), - }, - PoolAsset { - token: Some(Coin { - denom: "uosmo".to_string(), - amount: "200".to_string(), - }), - weight: "80".to_string(), - }, - ], - total_weight: "100".to_string(), - }; - - let valence_xyk_pool = OsmosisXykPool(pool).try_to_canonical().unwrap(); - println!("parsed xyk pool: {:?}", valence_xyk_pool); - - assert_eq!(valence_xyk_pool.assets.len(), 2); - assert_eq!(valence_xyk_pool.assets[0], coin(100, "uatom")); - assert_eq!(valence_xyk_pool.assets[1], coin(200, "uosmo")); - assert_eq!(valence_xyk_pool.total_shares, "1000"); - } - } -} - -pub mod icq { - use std::collections::BTreeMap; - - use cosmwasm_std::{to_json_binary, Binary, StdError, StdResult}; - use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; - use osmosis_std::{shim::Any, types::osmosis::gamm::v1beta1::Pool}; - use valence_canonical_types::try_unpack_domain_specific_value; - use valence_middleware_utils::IcqIntegration; - - use prost::Message; - - use super::OsmosisXykPool; - - impl IcqIntegration for OsmosisXykPool { - fn get_kv_key(&self, params: BTreeMap) -> StdResult { - let pool_prefix_key: u8 = 0x02; - - let id: u64 = try_unpack_domain_specific_value("pool_id", ¶ms)?; - - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&id.to_be_bytes()); - - Ok(KVKey { - path: "gamm".to_string(), - key: Binary::new(pool_access_key), - }) - } - - fn decode_and_reconstruct( - query_id: String, - icq_result: InterchainQueryResult, - ) -> StdResult { - let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))?; - - let osmo_pool: Pool = any_msg - .try_into() - .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; - - to_json_binary(&osmo_pool) - } - } - - #[cfg(test)] - mod tests { - use super::*; - use cosmwasm_std::{from_json, to_json_binary, Binary}; - use neutron_sdk::bindings::types::StorageValue; - use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolAsset, PoolParams}; - - #[test] - fn test_get_kv_key() { - let pool = Pool::default(); - let mut params = BTreeMap::new(); - params.insert("pool_id".to_string(), to_json_binary(&1u64).unwrap()); - - let kv_key = OsmosisXykPool(pool).get_kv_key(params).unwrap(); - let b64_key = "AgAAAAAAAAAB"; - let binary_key = Binary::from_base64(b64_key).unwrap(); - - assert_eq!(kv_key.path, "gamm"); - assert_eq!(kv_key.key, Binary::new(vec![2, 0, 0, 0, 0, 0, 0, 0, 1])); - assert_eq!(kv_key.key, binary_key); - } - - #[test] - fn test_decode_and_reconstruct() { - let b64_key = "AgAAAAAAAAAB"; - let binary_key = Binary::from_base64(b64_key).unwrap(); - - let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; - let binary_value = Binary::from_base64(b64_value).unwrap(); - - let storage_value = StorageValue { - storage_prefix: "gamm".to_string(), - key: binary_key, - value: binary_value, - }; - - let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( - Pool::TYPE_URL.to_string(), - InterchainQueryResult { - kv_results: vec![storage_value], - height: 1, - revision: 1, - }, - ) - .unwrap(); - - let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); - - assert_eq!( - osmo_pool.address, - "osmo19e2mf7cywkv7zaug6nk5f87d07fxrdgrladvymh2gwv5crvm3vnsuewhh7".to_string() - ); - assert_eq!(osmo_pool.id, 1); - assert_eq!( - osmo_pool.pool_params, - Some(PoolParams { - swap_fee: "0".to_string(), - exit_fee: "0".to_string(), - smooth_weight_change_params: None - }) - ); - assert_eq!(osmo_pool.future_pool_governor, "128h".to_string()); - assert_eq!( - osmo_pool.total_shares, - Some(osmosis_std::types::cosmos::base::v1beta1::Coin { - denom: "gamm/pool/1".to_string(), - amount: "100000000000000000000".to_string() - }) - ); - assert_eq!(osmo_pool.pool_assets.len(), 2); - assert_eq!( - osmo_pool.pool_assets[0], - PoolAsset { - token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { - denom: - "ibc/4E41ED8F3DCAEA15F4D6ADC6EDD7C04A676160735C9710B904B7BF53525B56D6" - .to_string(), - amount: "100000000".to_string() - }), - weight: "1073741824".to_string() - } - ); - assert_eq!( - osmo_pool.pool_assets[1], - PoolAsset { - token: Some(osmosis_std::types::cosmos::base::v1beta1::Coin { - denom: "uosmo".to_string(), - amount: "100000000".to_string() - }), - weight: "1073741824".to_string() - } - ); - assert_eq!(osmo_pool.total_weight, "2147483648"); - } - } -} - -#[cfg(test)] -mod tests { - use cosmwasm_std::{from_json, Binary}; - use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; - use osmosis_std::types::osmosis::gamm::v1beta1::Pool; - use valence_canonical_types::pools::xyk::ValenceXykAdapter; - use valence_middleware_utils::IcqIntegration; - - use crate::osmo_gamm_pool::OsmosisXykPool; - - #[test] - fn e2e() { - let b64_key = "AgAAAAAAAAAB"; - let binary_key = Binary::from_base64(b64_key).unwrap(); - - let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; - let binary_value = Binary::from_base64(b64_value).unwrap(); - - let storage_value = StorageValue { - storage_prefix: "gamm".to_string(), - key: binary_key, - value: binary_value, - }; - - // first we simulate the icq result reconstruction of b64(proto) -> type -> b64(type) - let osmo_pool_binary = OsmosisXykPool::decode_and_reconstruct( - Pool::TYPE_URL.to_string(), - InterchainQueryResult { - kv_results: vec![storage_value], - height: 1, - revision: 1, - }, - ) - .unwrap(); - - // unpack the binary into a type - let osmo_pool: Pool = from_json(osmo_pool_binary).unwrap(); - - // parse the external type into a valence type - - let mut valence_pool = OsmosisXykPool(osmo_pool).try_to_canonical().unwrap(); - - // simulate modifying the pool instance - valence_pool.assets.push(cosmwasm_std::coin(100, "batom")); - valence_pool.domain_specific_fields.insert( - "pool_asset_batom_weight".to_string(), - cosmwasm_std::to_json_binary(&"120").unwrap(), - ); - - // convert the valence type back into the external type - let osmo_pool = OsmosisXykPool::try_from_canonical(valence_pool).unwrap(); - - assert_eq!(osmo_pool.pool_assets.len(), 3); - } -} diff --git a/packages/canonical-types/Cargo.toml b/packages/canonical-types/Cargo.toml deleted file mode 100644 index bfea9699..00000000 --- a/packages/canonical-types/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "valence-canonical-types" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -description = "canonical types for Valence Protocol" - -[dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -serde = { workspace = true } diff --git a/packages/canonical-types/src/lib.rs b/packages/canonical-types/src/lib.rs deleted file mode 100644 index 20066e31..00000000 --- a/packages/canonical-types/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::collections::BTreeMap; - -use cosmwasm_std::{from_json, StdError, StdResult}; -use serde::de::DeserializeOwned; - -pub mod pools; - -pub fn try_unpack_domain_specific_value( - key: &str, - domain_specific_fields: &BTreeMap, -) -> StdResult -where - T: DeserializeOwned, -{ - let binary = domain_specific_fields - .get(key) - .ok_or(StdError::generic_err(format!( - "failed to get {} field from domain specific fields", - key - ))) - .unwrap(); - - from_json(binary) -} diff --git a/packages/middleware-utils/Cargo.toml b/packages/middleware-utils/Cargo.toml index 7d55b1d5..bce8bb20 100644 --- a/packages/middleware-utils/Cargo.toml +++ b/packages/middleware-utils/Cargo.toml @@ -8,5 +8,6 @@ description = "valence middleware utilities" [dependencies] cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } -valence-canonical-types = { workspace = true } +# valence-canonical-types = { workspace = true } neutron-sdk = { workspace = true } +thiserror = { workspace = true } diff --git a/packages/middleware-utils/src/canonical_types/mod.rs b/packages/middleware-utils/src/canonical_types/mod.rs new file mode 100644 index 00000000..17f66413 --- /dev/null +++ b/packages/middleware-utils/src/canonical_types/mod.rs @@ -0,0 +1 @@ +pub mod pools; diff --git a/packages/canonical-types/src/pools/mod.rs b/packages/middleware-utils/src/canonical_types/pools/mod.rs similarity index 100% rename from packages/canonical-types/src/pools/mod.rs rename to packages/middleware-utils/src/canonical_types/pools/mod.rs diff --git a/packages/canonical-types/src/pools/xyk.rs b/packages/middleware-utils/src/canonical_types/pools/xyk.rs similarity index 93% rename from packages/canonical-types/src/pools/xyk.rs rename to packages/middleware-utils/src/canonical_types/pools/xyk.rs index 1196fd8c..e5d74382 100644 --- a/packages/canonical-types/src/pools/xyk.rs +++ b/packages/middleware-utils/src/canonical_types/pools/xyk.rs @@ -3,6 +3,8 @@ use std::collections::BTreeMap; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ensure, Binary, Coin, Decimal, StdError, StdResult}; +use crate::MiddlewareError; + #[cw_serde] pub struct ValenceXykPool { /// assets in the pool @@ -31,8 +33,8 @@ impl ValenceXykPool { pub trait ValenceXykAdapter { type External; - fn try_to_canonical(&self) -> StdResult; - fn try_from_canonical(canonical: ValenceXykPool) -> StdResult; + fn try_to_canonical(&self) -> Result; + fn try_from_canonical(canonical: ValenceXykPool) -> Result; } /* diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index 9d6b3de0..dbe351d4 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -1,25 +1,42 @@ +use cosmwasm_schema::serde::de::DeserializeOwned; use std::collections::BTreeMap; +use thiserror::Error; -use cosmwasm_std::{Binary, StdResult}; +use cosmwasm_std::{from_json, Binary, StdError, StdResult}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; -// use valence_canonical_types::pools::xyk::ValenceXykPool; -// pub trait ValenceTypeAdapter { -// type External; - -// fn to_canonical(&self) -> StdResult; -// fn from_canonical(canonical: ValenceXykPool) -> StdResult; -// } - -pub trait MiddlewareSerializer: Sized { - fn serialize(&self) -> StdResult; - fn deserialize(binary: Binary) -> StdResult; -} +pub mod canonical_types; pub trait IcqIntegration { - fn get_kv_key(&self, params: BTreeMap) -> StdResult; + fn get_kv_key(&self, params: BTreeMap) -> Result; fn decode_and_reconstruct( query_id: String, icq_result: InterchainQueryResult, - ) -> StdResult; + ) -> Result; +} + +#[derive(Error, Debug, PartialEq)] +pub enum MiddlewareError { + #[error("{0}")] + Std(#[from] StdError), + // #[error("Processor is currently paused")] + // ProcessorPaused {}, +} + +pub fn try_unpack_domain_specific_value( + key: &str, + domain_specific_fields: &BTreeMap, +) -> StdResult +where + T: DeserializeOwned, +{ + let binary = domain_specific_fields + .get(key) + .ok_or(StdError::generic_err(format!( + "failed to get {} field from domain specific fields", + key + ))) + .unwrap(); + + from_json(binary) } From 9cdaa37001a2d8161e050be56950bf82def57a9b Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 17:19:37 +0100 Subject: [PATCH 72/92] cleanup org --- Cargo.lock | 1 + Cargo.toml | 2 ++ .../domains/osmosis/osmo-26-0-0/Cargo.toml | 5 ++--- .../definitions/gamm_pool/domain_adapter.rs | 9 +++----- .../definitions/gamm_pool/valence_adapter.rs | 7 ++----- packages/middleware-utils/Cargo.toml | 4 ++-- .../src/canonical_types/pools/xyk.rs | 21 ++++++++++++------- packages/middleware-utils/src/lib.rs | 8 +++++-- 8 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83818452..c5828577 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5335,6 +5335,7 @@ dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", "neutron-sdk", + "prost 0.13.3", "thiserror 1.0.69", ] diff --git a/Cargo.toml b/Cargo.toml index 4583a4e8..eacc39ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,3 +111,5 @@ tokio = "1.40.0" osmosis-test-tube = "26.0.1" env_logger = "0.11.5" log = "0.4.22" +prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } +prost-types = { version = "0.13.3", default-features = false } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml index 4ced8c44..e7f61bf6 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml @@ -19,14 +19,13 @@ cosmwasm-schema = { workspace = true } cw-ownable = { workspace = true } osmosis-std = "0.26.0" osmosis-std-derive = "0.26.0" -prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } -prost-types = { version = "0.13.3", default-features = false } +prost = { workspace = true } +prost-types = { workspace = true } neutron-sdk = { workspace = true } serde-json-wasm = { version = "1.0.0", default-features = false } thiserror = { workspace = true } serde_json = { workspace = true } cw-storage-plus = { workspace = true } -# valence-canonical-types = { workspace = true } valence-middleware-utils = { workspace = true } [dev-dependencies] diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs index 68277044..f04c8066 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs @@ -2,7 +2,7 @@ use osmosis_std::types::osmosis::gamm::v1beta1::Pool; use std::collections::BTreeMap; -use cosmwasm_std::{to_json_binary, Binary, StdError}; +use cosmwasm_std::{to_json_binary, Binary}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use osmosis_std::shim::Any; use valence_middleware_utils::{try_unpack_domain_specific_value, IcqIntegration, MiddlewareError}; @@ -30,12 +30,9 @@ impl IcqIntegration for OsmosisXykPool { query_id: String, icq_result: InterchainQueryResult, ) -> Result { - let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))?; + let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice())?; - let osmo_pool: Pool = any_msg - .try_into() - .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; + let osmo_pool: Pool = any_msg.try_into()?; let binary = to_json_binary(&osmo_pool)?; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs index 164aa28b..9a2188f6 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs @@ -1,8 +1,8 @@ use std::collections::BTreeMap; use std::str::FromStr; +use cosmwasm_std::coin; use cosmwasm_std::to_json_binary; -use cosmwasm_std::{coin, StdError}; use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; @@ -53,10 +53,7 @@ impl ValenceXykAdapter for OsmosisXykPool { let mut assets = vec![]; for asset in &self.0.pool_assets { if let Some(t) = &asset.token { - assets.push(coin( - u128::from_str(&t.amount).map_err(|e| StdError::generic_err(e.to_string()))?, - t.denom.to_string(), - )); + assets.push(coin(u128::from_str(&t.amount)?, t.denom.to_string())); } } diff --git a/packages/middleware-utils/Cargo.toml b/packages/middleware-utils/Cargo.toml index bce8bb20..b5ae2be4 100644 --- a/packages/middleware-utils/Cargo.toml +++ b/packages/middleware-utils/Cargo.toml @@ -8,6 +8,6 @@ description = "valence middleware utilities" [dependencies] cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } -# valence-canonical-types = { workspace = true } -neutron-sdk = { workspace = true } +neutron-sdk = { workspace = true } thiserror = { workspace = true } +prost = { workspace = true } diff --git a/packages/middleware-utils/src/canonical_types/pools/xyk.rs b/packages/middleware-utils/src/canonical_types/pools/xyk.rs index e5d74382..ed6216b2 100644 --- a/packages/middleware-utils/src/canonical_types/pools/xyk.rs +++ b/packages/middleware-utils/src/canonical_types/pools/xyk.rs @@ -5,12 +5,21 @@ use cosmwasm_std::{ensure, Binary, Coin, Decimal, StdError, StdResult}; use crate::MiddlewareError; +pub trait ValenceXykAdapter { + type External; + + fn try_to_canonical(&self) -> Result; + fn try_from_canonical(canonical: ValenceXykPool) -> Result; +} + #[cw_serde] pub struct ValenceXykPool { /// assets in the pool pub assets: Vec, + /// total amount of shares issued pub total_shares: String, + /// any other fields that are unique to the external pool type /// being represented by this struct pub domain_specific_fields: BTreeMap, @@ -23,6 +32,11 @@ impl ValenceXykPool { StdError::generic_err("price can be calculated iff xyk pool contains exactly 2 assets") ); + ensure!( + !self.assets[0].amount.is_zero() && !self.assets[1].amount.is_zero(), + StdError::generic_err("price can't be calculated if any of the assets amount is zero") + ); + let a = self.assets[0].amount; let b = self.assets[1].amount; @@ -30,13 +44,6 @@ impl ValenceXykPool { } } -pub trait ValenceXykAdapter { - type External; - - fn try_to_canonical(&self) -> Result; - fn try_from_canonical(canonical: ValenceXykPool) -> Result; -} - /* OSMOSIS POOL diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index dbe351d4..d68be391 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -19,8 +19,12 @@ pub trait IcqIntegration { pub enum MiddlewareError { #[error("{0}")] Std(#[from] StdError), - // #[error("Processor is currently paused")] - // ProcessorPaused {}, + + #[error("{0}")] + ParseIntError(#[from] std::num::ParseIntError), + + #[error("{0}")] + DecodeError(#[from] prost::DecodeError), } pub fn try_unpack_domain_specific_value( From 4b9c6802fa9662032367cdfec71354bdf4e26f64 Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 21:25:48 +0100 Subject: [PATCH 73/92] base bank balance integration --- .../osmosis/osmo-26-0-0/src/contract.rs | 13 ++- .../bank_balance/domain_adapter.rs | 98 +++++++++++++++++++ .../src/definitions/bank_balance/mod.rs | 9 ++ .../bank_balance/valence_adapter.rs | 21 ++++ .../osmo-26-0-0/src/definitions/mod.rs | 12 +++ .../domains/osmosis/osmo-26-0-0/src/msg.rs | 7 +- .../src/canonical_types/bank/balance.rs | 17 ++++ .../src/canonical_types/bank/mod.rs | 1 + .../src/canonical_types/mod.rs | 1 + packages/middleware-utils/src/lib.rs | 8 +- 10 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs create mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs create mode 100644 packages/middleware-utils/src/canonical_types/bank/balance.rs create mode 100644 packages/middleware-utils/src/canonical_types/bank/mod.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 9dd94e67..98dd954e 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -7,7 +7,10 @@ use cosmwasm_std::{ }; use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; -use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use crate::{ + definitions::ValenceType, + msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, +}; // version info for migration info const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); @@ -44,14 +47,14 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } } -fn try_serialize_obj(object: ValenceXykPool) -> StdResult { +fn try_serialize_obj(object: ValenceType) -> StdResult { Ok(Binary::new("a".as_bytes().to_vec())) } -fn try_deserialize_type_url(type_url: String, binary: Binary) -> StdResult { - Ok(ValenceXykPool { +fn try_deserialize_type_url(type_url: String, binary: Binary) -> StdResult { + Ok(ValenceType::ValenceXykPool(ValenceXykPool { assets: vec![], total_shares: "hi".to_string(), domain_specific_fields: BTreeMap::new(), - }) + })) } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs new file mode 100644 index 00000000..7e727fb2 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs @@ -0,0 +1,98 @@ +use std::collections::BTreeMap; + +use cosmwasm_std::{to_json_binary, Binary}; +use neutron_sdk::{ + bindings::types::{InterchainQueryResult, KVKey}, + interchain_queries::{ + helpers::decode_and_convert, + types::KVReconstruct, + v047::{ + helpers::create_account_denom_balance_key, + types::{Balances, BANK_STORE_KEY}, + }, + }, +}; +use valence_middleware_utils::{try_unpack_domain_specific_value, IcqIntegration, MiddlewareError}; + +use super::{OsmosisBankBalance, ADDR_KEY, DENOM_KEY}; + +impl IcqIntegration for OsmosisBankBalance { + fn get_kv_key(&self, params: BTreeMap) -> Result { + let addr: String = try_unpack_domain_specific_value(ADDR_KEY, ¶ms)?; + let denom: String = try_unpack_domain_specific_value(DENOM_KEY, ¶ms)?; + + let converted_addr_bytes = decode_and_convert(&addr)?; + + let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); + + Ok(KVKey { + path: BANK_STORE_KEY.to_string(), + key: Binary::new(balance_key), + }) + } + + fn decode_and_reconstruct( + query_id: String, + icq_result: InterchainQueryResult, + ) -> Result { + let balances: Balances = KVReconstruct::reconstruct(&icq_result.kv_results)?; + + Ok(to_json_binary(&balances)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::from_json; + use neutron_sdk::bindings::types::StorageValue; + use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; + + #[test] + fn test_get_kv_key() { + let qb_response = QueryBalanceResponse::default(); + let mut params = BTreeMap::new(); + + params.insert( + ADDR_KEY.to_string(), + to_json_binary(&"osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63").unwrap(), + ); + params.insert(DENOM_KEY.to_string(), to_json_binary(&"uosmo").unwrap()); + + let kvk_response = OsmosisBankBalance(qb_response).get_kv_key(params).unwrap(); + + let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); + + assert_eq!(kvk_response.path, "bank".to_string()); + assert_eq!(kvk_response.key, key_binary); + } + + #[test] + fn test_decode_and_reconstruct() { + let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); + let value_binary = Binary::from_base64("OTk5ODg5OTk5NzUwMA==").unwrap(); + + let icq_result = InterchainQueryResult { + kv_results: vec![StorageValue { + key: key_binary, + value: value_binary, + storage_prefix: "bank".to_string(), + }], + height: 1, + revision: 1, + }; + + let result = OsmosisBankBalance::decode_and_reconstruct( + QueryBalanceResponse::TYPE_URL.to_string(), + icq_result, + ) + .unwrap(); + + let balance_response: Balances = from_json(result).unwrap(); + + assert_eq!(balance_response.coins.len(), 1); + + assert_eq!(balance_response.coins[0].denom, "uosmo"); + assert_eq!(balance_response.coins[0].amount.u128(), 9998899997500); + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs new file mode 100644 index 00000000..fd97e624 --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs @@ -0,0 +1,9 @@ +use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; + +pub mod domain_adapter; +pub mod valence_adapter; + +const ADDR_KEY: &str = "addr"; +const DENOM_KEY: &str = "denom"; + +pub struct OsmosisBankBalance(pub QueryBalanceResponse); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs new file mode 100644 index 00000000..c5341fad --- /dev/null +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs @@ -0,0 +1,21 @@ +use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; +use valence_middleware_utils::{ + canonical_types::bank::balance::{ValenceBankBalance, ValenceBankBalanceAdapter}, + MiddlewareError, +}; + +use super::OsmosisBankBalance; + +impl ValenceBankBalanceAdapter for OsmosisBankBalance { + type External = QueryBalanceResponse; + + fn try_to_canonical(&self) -> Result { + todo!() + } + + fn try_from_canonical( + canonical: ValenceBankBalance, + ) -> Result { + todo!() + } +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs index a4f13977..9981b9a6 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -1 +1,13 @@ +use cosmwasm_schema::cw_serde; +use valence_middleware_utils::canonical_types::{ + bank::balance::ValenceBankBalance, pools::xyk::ValenceXykPool, +}; + +pub mod bank_balance; pub mod gamm_pool; + +#[cw_serde] +pub enum ValenceType { + ValenceXykPool(ValenceXykPool), + ValenceBankBalance(ValenceBankBalance), +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs index 35effc5a..69ac6741 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs @@ -1,6 +1,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Binary; -use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; + +use crate::definitions::ValenceType; #[cw_serde] pub struct InstantiateMsg {} @@ -12,9 +13,9 @@ pub enum ExecuteMsg {} pub enum QueryMsg { /// serialize a message to binary #[returns(Binary)] - Serialize { obj: ValenceXykPool }, + Serialize { obj: ValenceType }, /// deserialize a message from binary/bytes - #[returns(ValenceXykPool)] + #[returns(ValenceType)] Deserialize { type_url: String, binary: Binary }, // TODO: transform an outdated type to a new version } diff --git a/packages/middleware-utils/src/canonical_types/bank/balance.rs b/packages/middleware-utils/src/canonical_types/bank/balance.rs new file mode 100644 index 00000000..1ea9e455 --- /dev/null +++ b/packages/middleware-utils/src/canonical_types/bank/balance.rs @@ -0,0 +1,17 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::Coin; + +use crate::MiddlewareError; + +pub trait ValenceBankBalanceAdapter { + type External; + + fn try_to_canonical(&self) -> Result; + fn try_from_canonical(canonical: ValenceBankBalance) + -> Result; +} + +#[cw_serde] +pub struct ValenceBankBalance { + pub assets: Vec, +} diff --git a/packages/middleware-utils/src/canonical_types/bank/mod.rs b/packages/middleware-utils/src/canonical_types/bank/mod.rs new file mode 100644 index 00000000..6844c2b6 --- /dev/null +++ b/packages/middleware-utils/src/canonical_types/bank/mod.rs @@ -0,0 +1 @@ +pub mod balance; diff --git a/packages/middleware-utils/src/canonical_types/mod.rs b/packages/middleware-utils/src/canonical_types/mod.rs index 17f66413..50e49e71 100644 --- a/packages/middleware-utils/src/canonical_types/mod.rs +++ b/packages/middleware-utils/src/canonical_types/mod.rs @@ -1 +1,2 @@ +pub mod bank; pub mod pools; diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index d68be391..fe73745c 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -3,7 +3,10 @@ use std::collections::BTreeMap; use thiserror::Error; use cosmwasm_std::{from_json, Binary, StdError, StdResult}; -use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; +use neutron_sdk::{ + bindings::types::{InterchainQueryResult, KVKey}, + NeutronError, +}; pub mod canonical_types; @@ -25,6 +28,9 @@ pub enum MiddlewareError { #[error("{0}")] DecodeError(#[from] prost::DecodeError), + + #[error("{0}")] + NeutronError(#[from] NeutronError), } pub fn try_unpack_domain_specific_value( From 9756fecb2d2bf51834e1d429857f7d95c400758c Mon Sep 17 00:00:00 2001 From: bekauz Date: Mon, 16 Dec 2024 21:41:16 +0100 Subject: [PATCH 74/92] integrate balance query into valence types --- .../bank_balance/valence_adapter.rs | 70 ++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs index c5341fad..8ec27d61 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs @@ -1,4 +1,6 @@ +use cosmwasm_std::{coins, StdError}; use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; +use osmosis_std::types::cosmos::base::v1beta1::Coin as ProtoCoin; use valence_middleware_utils::{ canonical_types::bank::balance::{ValenceBankBalance, ValenceBankBalanceAdapter}, MiddlewareError, @@ -10,12 +12,76 @@ impl ValenceBankBalanceAdapter for OsmosisBankBalance { type External = QueryBalanceResponse; fn try_to_canonical(&self) -> Result { - todo!() + match &self.0.balance { + Some(coin) => { + let amount_u128 = coin.amount.parse::()?; + + Ok(ValenceBankBalance { + assets: coins(amount_u128, coin.denom.to_string()), + }) + } + None => Err(MiddlewareError::Std(StdError::generic_err( + "failed to find coin in QueryBalanceResponse", + ))), + } } fn try_from_canonical( canonical: ValenceBankBalance, ) -> Result { - todo!() + let balance: Option = match canonical.assets.len() { + 0 => None, + 1 => { + let coin = canonical.assets.into_iter().next().unwrap(); + Some(coin.into()) + } + _ => { + return Err(MiddlewareError::Std(StdError::generic_err( + "failed to convert multiple coins into QueryBalanceResponse", + ))) + } + }; + Ok(QueryBalanceResponse { balance }) + } +} + +#[cfg(test)] +mod tests { + use cosmwasm_std::coins; + use osmosis_std::types::cosmos::{ + bank::v1beta1::QueryBalanceResponse, base::v1beta1::Coin as ProtoCoin, + }; + use valence_middleware_utils::canonical_types::bank::balance::{ + ValenceBankBalance, ValenceBankBalanceAdapter, + }; + + use crate::definitions::bank_balance::OsmosisBankBalance; + + #[test] + fn test_try_from_canonical() { + let canonical = ValenceBankBalance { + assets: coins(100, "uosmo"), + }; + let result = OsmosisBankBalance::try_from_canonical(canonical).unwrap(); + let result_coin = result.balance.unwrap(); + + assert_eq!(result_coin.amount, "100"); + assert_eq!(result_coin.denom, "uosmo"); + } + + #[test] + fn test_try_to_canonical() { + let osmosis_bank_balance = OsmosisBankBalance(QueryBalanceResponse { + balance: Some(ProtoCoin { + denom: "uosmo".to_string(), + amount: "100".to_string(), + }), + }); + + let result = osmosis_bank_balance.try_to_canonical().unwrap(); + + assert_eq!(result.assets.len(), 1); + assert_eq!(result.assets[0].amount.u128(), 100); + assert_eq!(result.assets[0].denom, "uosmo"); } } From 181f533a1da73444a2b8425ecdd9ef8fa3a4ccba Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 12:25:01 +0100 Subject: [PATCH 75/92] init broker --- Cargo.lock | 20 +++++++++++ Cargo.toml | 2 ++ .../brokers/osmo-broker/.cargo/config.toml | 3 ++ .../middleware/brokers/osmo-broker/Cargo.toml | 32 ++++++++++++++++++ .../middleware/brokers/osmo-broker/README.md | 0 .../brokers/osmo-broker/src/contract.rs | 33 +++++++++++++++++++ .../middleware/brokers/osmo-broker/src/lib.rs | 3 ++ .../middleware/brokers/osmo-broker/src/msg.rs | 0 .../brokers/osmo-broker/src/state.rs | 0 packages/middleware-utils/src/broker/mod.rs | 1 + packages/middleware-utils/src/broker/types.rs | 10 ++++++ packages/middleware-utils/src/lib.rs | 1 + 12 files changed, 105 insertions(+) create mode 100644 contracts/middleware/brokers/osmo-broker/.cargo/config.toml create mode 100644 contracts/middleware/brokers/osmo-broker/Cargo.toml create mode 100644 contracts/middleware/brokers/osmo-broker/README.md create mode 100644 contracts/middleware/brokers/osmo-broker/src/contract.rs create mode 100644 contracts/middleware/brokers/osmo-broker/src/lib.rs create mode 100644 contracts/middleware/brokers/osmo-broker/src/msg.rs create mode 100644 contracts/middleware/brokers/osmo-broker/src/state.rs create mode 100644 packages/middleware-utils/src/broker/mod.rs create mode 100644 packages/middleware-utils/src/broker/types.rs diff --git a/Cargo.lock b/Cargo.lock index c5828577..240dea47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5308,6 +5308,26 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "valence-middleware-broker-osmosis" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema 2.1.4", + "cosmwasm-std 2.1.4", + "cw-ownable", + "cw-storage-plus 2.0.0", + "neutron-sdk", + "osmosis-std", + "osmosis-std-derive", + "osmosis-test-tube", + "prost 0.13.3", + "prost-types 0.13.3", + "serde-json-wasm 1.0.1", + "serde_json", + "thiserror 1.0.69", + "valence-middleware-utils", +] + [[package]] name = "valence-middleware-osmosis" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index eacc39ae..9f418aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "contracts/testing/*", "contracts/program-registry", "contracts/middleware/domains/osmosis/osmo-26-0-0", + "contracts/middleware/brokers/osmo-broker", "packages/*", "program-manager", "local-interchaintest", @@ -77,6 +78,7 @@ valence-icq-querier = { path = "contracts/libraries/icq-querier # middleware valence-middleware-osmosis = { path = "contracts/middleware/domains/osmosis/osmo-26-0-0", features = ["library"] } +valence-middleware-broker-osmosis = { path = "contracts/middleware/brokers/osmo-broker", features = ["library"] } # our packages valence-account-utils = { path = "packages/account-utils" } diff --git a/contracts/middleware/brokers/osmo-broker/.cargo/config.toml b/contracts/middleware/brokers/osmo-broker/.cargo/config.toml new file mode 100644 index 00000000..5f6aa466 --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/.cargo/config.toml @@ -0,0 +1,3 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +schema = "run --bin schema" diff --git a/contracts/middleware/brokers/osmo-broker/Cargo.toml b/contracts/middleware/brokers/osmo-broker/Cargo.toml new file mode 100644 index 00000000..48c6d67a --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "valence-middleware-broker-osmosis" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +version = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-ownable = { workspace = true } +osmosis-std = "0.26.0" +osmosis-std-derive = "0.26.0" +prost = { workspace = true } +prost-types = { workspace = true } +neutron-sdk = { workspace = true } +serde-json-wasm = { version = "1.0.0", default-features = false } +thiserror = { workspace = true } +serde_json = { workspace = true } +cw-storage-plus = { workspace = true } +valence-middleware-utils = { workspace = true } + +[dev-dependencies] +osmosis-test-tube = { workspace = true } diff --git a/contracts/middleware/brokers/osmo-broker/README.md b/contracts/middleware/brokers/osmo-broker/README.md new file mode 100644 index 00000000..e69de29b diff --git a/contracts/middleware/brokers/osmo-broker/src/contract.rs b/contracts/middleware/brokers/osmo-broker/src/contract.rs new file mode 100644 index 00000000..5bfb562a --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/src/contract.rs @@ -0,0 +1,33 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; +use valence_middleware_utils::broker::types::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +// version info for migration info +const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: ExecuteMsg, +) -> Result { + Ok(Response::default()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + Err(StdError::generic_err("unimplemented")) +} diff --git a/contracts/middleware/brokers/osmo-broker/src/lib.rs b/contracts/middleware/brokers/osmo-broker/src/lib.rs new file mode 100644 index 00000000..4934c19d --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/src/lib.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod msg; +pub mod state; diff --git a/contracts/middleware/brokers/osmo-broker/src/msg.rs b/contracts/middleware/brokers/osmo-broker/src/msg.rs new file mode 100644 index 00000000..e69de29b diff --git a/contracts/middleware/brokers/osmo-broker/src/state.rs b/contracts/middleware/brokers/osmo-broker/src/state.rs new file mode 100644 index 00000000..e69de29b diff --git a/packages/middleware-utils/src/broker/mod.rs b/packages/middleware-utils/src/broker/mod.rs new file mode 100644 index 00000000..cd408564 --- /dev/null +++ b/packages/middleware-utils/src/broker/mod.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/packages/middleware-utils/src/broker/types.rs b/packages/middleware-utils/src/broker/types.rs new file mode 100644 index 00000000..876f64ab --- /dev/null +++ b/packages/middleware-utils/src/broker/types.rs @@ -0,0 +1,10 @@ +use cosmwasm_schema::cw_serde; + +#[cw_serde] +pub struct InstantiateMsg {} + +#[cw_serde] +pub enum ExecuteMsg {} + +#[cw_serde] +pub enum QueryMsg {} diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index fe73745c..a8aad41d 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -8,6 +8,7 @@ use neutron_sdk::{ NeutronError, }; +pub mod broker; pub mod canonical_types; pub trait IcqIntegration { From e3a00e094cface852d10a39037e4af89d6cabf7d Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 16:38:51 +0100 Subject: [PATCH 76/92] registry cntd; init type_registry type mod in utils --- Cargo.lock | 6 +- Cargo.toml | 1 + .../middleware/brokers/osmo-broker/Cargo.toml | 1 + .../brokers/osmo-broker/src/contract.rs | 116 ++++++++++++++++-- .../middleware/brokers/osmo-broker/src/lib.rs | 1 - .../middleware/brokers/osmo-broker/src/msg.rs | 0 .../brokers/osmo-broker/src/state.rs | 5 + .../osmosis/osmo-26-0-0/src/contract.rs | 69 ++++++++--- .../bank_balance/domain_adapter.rs | 7 +- .../definitions/gamm_pool/domain_adapter.rs | 16 +-- .../osmo-26-0-0/src/definitions/mod.rs | 8 +- .../domains/osmosis/osmo-26-0-0/src/lib.rs | 1 - .../domains/osmosis/osmo-26-0-0/src/msg.rs | 21 ---- packages/middleware-utils/Cargo.toml | 1 + packages/middleware-utils/src/broker/types.rs | 30 ++++- packages/middleware-utils/src/lib.rs | 12 +- .../middleware-utils/src/type_registry/mod.rs | 1 + .../src/type_registry/types.rs | 42 +++++++ 18 files changed, 263 insertions(+), 75 deletions(-) delete mode 100644 contracts/middleware/brokers/osmo-broker/src/msg.rs delete mode 100644 contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs create mode 100644 packages/middleware-utils/src/type_registry/mod.rs create mode 100644 packages/middleware-utils/src/type_registry/types.rs diff --git a/Cargo.lock b/Cargo.lock index 240dea47..8ff12b10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3928,9 +3928,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" @@ -5322,6 +5322,7 @@ dependencies = [ "osmosis-test-tube", "prost 0.13.3", "prost-types 0.13.3", + "semver", "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", @@ -5356,6 +5357,7 @@ dependencies = [ "cosmwasm-std 2.1.4", "neutron-sdk", "prost 0.13.3", + "semver", "thiserror 1.0.69", ] diff --git a/Cargo.toml b/Cargo.toml index 9f418aee..e845e36c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,3 +115,4 @@ env_logger = "0.11.5" log = "0.4.22" prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } prost-types = { version = "0.13.3", default-features = false } +semver = "1.0.24" diff --git a/contracts/middleware/brokers/osmo-broker/Cargo.toml b/contracts/middleware/brokers/osmo-broker/Cargo.toml index 48c6d67a..60168218 100644 --- a/contracts/middleware/brokers/osmo-broker/Cargo.toml +++ b/contracts/middleware/brokers/osmo-broker/Cargo.toml @@ -27,6 +27,7 @@ thiserror = { workspace = true } serde_json = { workspace = true } cw-storage-plus = { workspace = true } valence-middleware-utils = { workspace = true } +semver = { workspace = true } [dev-dependencies] osmosis-test-tube = { workspace = true } diff --git a/contracts/middleware/brokers/osmo-broker/src/contract.rs b/contracts/middleware/brokers/osmo-broker/src/contract.rs index 5bfb562a..c62fe92b 100644 --- a/contracts/middleware/brokers/osmo-broker/src/contract.rs +++ b/contracts/middleware/brokers/osmo-broker/src/contract.rs @@ -1,33 +1,125 @@ +use std::{collections::BTreeMap, str::FromStr}; + #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; -use valence_middleware_utils::broker::types::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use neutron_sdk::bindings::types::InterchainQueryResult; +use semver::Version; +use valence_middleware_utils::{ + broker::types::{Broker, ExecuteMsg, InstantiateMsg, QueryMsg}, + type_registry::types::RegistryQueryMsg, + MiddlewareError, +}; + +use crate::state::{ACTIVE_REGISTRIES, LATEST}; // version info for migration info -const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - deps: DepsMut, + _deps: DepsMut, _env: Env, _info: MessageInfo, - msg: InstantiateMsg, -) -> Result { + _msg: InstantiateMsg, +) -> Result { Ok(Response::default()) } #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( - _deps: DepsMut, + deps: DepsMut, _env: Env, _info: MessageInfo, - _msg: ExecuteMsg, -) -> Result { - Ok(Response::default()) + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::SetLatestRegistry { version, address } => { + try_add_new_registry(deps, version, address) + } + } +} + +fn try_add_new_registry( + deps: DepsMut, + version: String, + addr: String, +) -> Result { + let addr = deps.api.addr_validate(&addr)?; + let version = Version::from_str(&version)?; + + let broker = Broker { + registry_address: addr, + version: version.to_string(), + }; + + ACTIVE_REGISTRIES.save(deps.storage, version.to_string(), &broker)?; + LATEST.save(deps.storage, &version.to_string())?; + + Ok(Response::new()) } #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - Err(StdError::generic_err("unimplemented")) + match msg { + QueryMsg::DecodeProto { + registry_version, + query_id, + icq_result, + } => try_decode_proto(deps, registry_version, query_id, icq_result), + QueryMsg::GetKVKey { + registry_version, + params, + } => try_get_kv_key(deps, registry_version, params), + QueryMsg::ToCanonical {} => try_to_canonical(), + QueryMsg::FromCanonical {} => try_from_canonical(), + } +} + +fn try_decode_proto( + deps: Deps, + registry_version: Option, + query_id: String, + icq_result: InterchainQueryResult, +) -> StdResult { + let target_registry = get_target_registry(deps, registry_version)?; + + let decoded_result = deps.querier.query_wasm_smart( + target_registry.registry_address, + &RegistryQueryMsg::ReconstructProto { + query_id, + icq_result, + }, + )?; + + Ok(decoded_result) +} + +fn try_get_kv_key( + deps: Deps, + registry_version: Option, + params: BTreeMap, +) -> StdResult { + let target_registry = get_target_registry(deps, registry_version)?; + + Ok(Binary::new("a".as_bytes().to_vec())) +} + +fn try_to_canonical() -> StdResult { + Ok(Binary::new("a".as_bytes().to_vec())) +} + +fn try_from_canonical() -> StdResult { + Ok(Binary::new("a".as_bytes().to_vec())) +} + +fn get_target_registry(deps: Deps, version: Option) -> StdResult { + // if version is specified, we use that. otherwise default to latest. + let target_version = match version { + Some(version) => version, + None => LATEST.load(deps.storage)?, + }; + // load the target registry + ACTIVE_REGISTRIES.load(deps.storage, target_version) } diff --git a/contracts/middleware/brokers/osmo-broker/src/lib.rs b/contracts/middleware/brokers/osmo-broker/src/lib.rs index 4934c19d..3407c199 100644 --- a/contracts/middleware/brokers/osmo-broker/src/lib.rs +++ b/contracts/middleware/brokers/osmo-broker/src/lib.rs @@ -1,3 +1,2 @@ pub mod contract; -pub mod msg; pub mod state; diff --git a/contracts/middleware/brokers/osmo-broker/src/msg.rs b/contracts/middleware/brokers/osmo-broker/src/msg.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/contracts/middleware/brokers/osmo-broker/src/state.rs b/contracts/middleware/brokers/osmo-broker/src/state.rs index e69de29b..47477fc2 100644 --- a/contracts/middleware/brokers/osmo-broker/src/state.rs +++ b/contracts/middleware/brokers/osmo-broker/src/state.rs @@ -0,0 +1,5 @@ +use cw_storage_plus::{Item, Map}; +use valence_middleware_utils::broker::types::Broker; + +pub const ACTIVE_REGISTRIES: Map = Map::new("active_registries"); +pub const LATEST: Item = Item::new("latest"); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 98dd954e..7759a5c3 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -5,23 +5,27 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; -use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; - -use crate::{ - definitions::ValenceType, - msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, +use neutron_sdk::bindings::types::InterchainQueryResult; +use valence_middleware_utils::{ + canonical_types::pools::xyk::ValenceXykPool, + type_registry::types::{ + RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, ValenceType, + }, + IcqIntegration, }; +use crate::definitions::{bank_balance::OsmosisBankBalance, gamm_pool::OsmosisXykPool}; + // version info for migration info -const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - deps: DepsMut, + _deps: DepsMut, _env: Env, _info: MessageInfo, - msg: InstantiateMsg, + _msg: RegistryInstantiateMsg, ) -> Result { Ok(Response::default()) } @@ -31,28 +35,61 @@ pub fn execute( _deps: DepsMut, _env: Env, _info: MessageInfo, - _msg: ExecuteMsg, + _msg: RegistryExecuteMsg, ) -> Result { Ok(Response::default()) } #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { +pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { match msg { - QueryMsg::Serialize { obj } => try_serialize_obj(obj), - QueryMsg::Deserialize { type_url, binary } => { + RegistryQueryMsg::Serialize { obj } => try_serialize_obj(obj), + RegistryQueryMsg::Deserialize { type_url, binary } => { let deser = try_deserialize_type_url(type_url, binary)?; to_json_binary(&deser) } + RegistryQueryMsg::KVKey { type_id, params } => try_get_kv_key(type_id, params), + RegistryQueryMsg::ReconstructProto { + query_id, + icq_result, + } => try_reconstruct_proto(query_id, icq_result), + } +} + +fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResult { + let kv_key = match type_id.as_str() { + "gamm_pool" => OsmosisXykPool::get_kv_key(params), + "bank_balances" => OsmosisBankBalance::get_kv_key(params), + _ => return Err(StdError::generic_err("unknown type_id")), + }; + + match kv_key { + Ok(kv) => to_json_binary(&kv), + Err(_) => Err(StdError::generic_err("failed to read kv key")), + } +} + +fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> StdResult { + let reconstruction_result = match type_id.as_str() { + "gamm_pool" => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), + "bank_balances" => OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result), + _ => return Err(StdError::generic_err("unknown type_id")), + }; + + match reconstruction_result { + Ok(res) => to_json_binary(&res), + Err(_) => Err(StdError::generic_err( + "failed to reconstruct type from proto", + )), } } -fn try_serialize_obj(object: ValenceType) -> StdResult { +fn try_serialize_obj(_object: ValenceType) -> StdResult { Ok(Binary::new("a".as_bytes().to_vec())) } -fn try_deserialize_type_url(type_url: String, binary: Binary) -> StdResult { - Ok(ValenceType::ValenceXykPool(ValenceXykPool { +fn try_deserialize_type_url(_type_url: String, _binary: Binary) -> StdResult { + Ok(ValenceType::XykPool(ValenceXykPool { assets: vec![], total_shares: "hi".to_string(), domain_specific_fields: BTreeMap::new(), diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs index 7e727fb2..8133a078 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs @@ -17,7 +17,7 @@ use valence_middleware_utils::{try_unpack_domain_specific_value, IcqIntegration, use super::{OsmosisBankBalance, ADDR_KEY, DENOM_KEY}; impl IcqIntegration for OsmosisBankBalance { - fn get_kv_key(&self, params: BTreeMap) -> Result { + fn get_kv_key(params: BTreeMap) -> Result { let addr: String = try_unpack_domain_specific_value(ADDR_KEY, ¶ms)?; let denom: String = try_unpack_domain_specific_value(DENOM_KEY, ¶ms)?; @@ -32,7 +32,7 @@ impl IcqIntegration for OsmosisBankBalance { } fn decode_and_reconstruct( - query_id: String, + _query_id: String, icq_result: InterchainQueryResult, ) -> Result { let balances: Balances = KVReconstruct::reconstruct(&icq_result.kv_results)?; @@ -50,7 +50,6 @@ mod tests { #[test] fn test_get_kv_key() { - let qb_response = QueryBalanceResponse::default(); let mut params = BTreeMap::new(); params.insert( @@ -59,7 +58,7 @@ mod tests { ); params.insert(DENOM_KEY.to_string(), to_json_binary(&"uosmo").unwrap()); - let kvk_response = OsmosisBankBalance(qb_response).get_kv_key(params).unwrap(); + let kvk_response = OsmosisBankBalance::get_kv_key(params).unwrap(); let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs index f04c8066..3e2a71b3 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs @@ -2,7 +2,7 @@ use osmosis_std::types::osmosis::gamm::v1beta1::Pool; use std::collections::BTreeMap; -use cosmwasm_std::{to_json_binary, Binary}; +use cosmwasm_std::{to_json_binary, Binary, StdError}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use osmosis_std::shim::Any; use valence_middleware_utils::{try_unpack_domain_specific_value, IcqIntegration, MiddlewareError}; @@ -12,7 +12,7 @@ use prost::Message; use super::{OsmosisXykPool, STORAGE_PREFIX}; impl IcqIntegration for OsmosisXykPool { - fn get_kv_key(&self, params: BTreeMap) -> Result { + fn get_kv_key(params: BTreeMap) -> Result { let pool_prefix_key: u8 = 0x02; let id: u64 = try_unpack_domain_specific_value("pool_id", ¶ms)?; @@ -27,12 +27,15 @@ impl IcqIntegration for OsmosisXykPool { } fn decode_and_reconstruct( - query_id: String, + _query_id: String, icq_result: InterchainQueryResult, ) -> Result { - let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice())?; + let any_msg: Any = Any::decode(icq_result.kv_results[0].value.as_slice()) + .map_err(|e| MiddlewareError::DecodeError(e.to_string()))?; - let osmo_pool: Pool = any_msg.try_into()?; + let osmo_pool: Pool = any_msg + .try_into() + .map_err(|_| StdError::generic_err("failed to parse into pool"))?; let binary = to_json_binary(&osmo_pool)?; @@ -49,11 +52,10 @@ mod tests { #[test] fn test_get_kv_key() { - let pool = Pool::default(); let mut params = BTreeMap::new(); params.insert("pool_id".to_string(), to_json_binary(&1u64).unwrap()); - let kv_key = OsmosisXykPool(pool).get_kv_key(params).unwrap(); + let kv_key = OsmosisXykPool::get_kv_key(params).unwrap(); let b64_key = "AgAAAAAAAAAB"; let binary_key = Binary::from_base64(b64_key).unwrap(); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs index 9981b9a6..a6f06a52 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -6,8 +6,6 @@ use valence_middleware_utils::canonical_types::{ pub mod bank_balance; pub mod gamm_pool; -#[cw_serde] -pub enum ValenceType { - ValenceXykPool(ValenceXykPool), - ValenceBankBalance(ValenceBankBalance), -} +// TODO: embed the previously deployed version identifier there +// to ensure that types declared here implement a 1-1 mapper from +// the outdated version to this one. diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs index 8a72c442..3f6d9b5a 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs @@ -1,3 +1,2 @@ pub mod contract; pub mod definitions; -pub mod msg; diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs deleted file mode 100644 index 69ac6741..00000000 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/msg.rs +++ /dev/null @@ -1,21 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Binary; - -use crate::definitions::ValenceType; - -#[cw_serde] -pub struct InstantiateMsg {} -#[cw_serde] -pub enum ExecuteMsg {} - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - /// serialize a message to binary - #[returns(Binary)] - Serialize { obj: ValenceType }, - /// deserialize a message from binary/bytes - #[returns(ValenceType)] - Deserialize { type_url: String, binary: Binary }, - // TODO: transform an outdated type to a new version -} diff --git a/packages/middleware-utils/Cargo.toml b/packages/middleware-utils/Cargo.toml index b5ae2be4..cec6018e 100644 --- a/packages/middleware-utils/Cargo.toml +++ b/packages/middleware-utils/Cargo.toml @@ -11,3 +11,4 @@ cosmwasm-schema = { workspace = true } neutron-sdk = { workspace = true } thiserror = { workspace = true } prost = { workspace = true } +semver = { workspace = true } diff --git a/packages/middleware-utils/src/broker/types.rs b/packages/middleware-utils/src/broker/types.rs index 876f64ab..71c9a07c 100644 --- a/packages/middleware-utils/src/broker/types.rs +++ b/packages/middleware-utils/src/broker/types.rs @@ -1,10 +1,36 @@ +use std::collections::BTreeMap; + use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Binary}; +use neutron_sdk::bindings::types::InterchainQueryResult; #[cw_serde] pub struct InstantiateMsg {} #[cw_serde] -pub enum ExecuteMsg {} +pub enum ExecuteMsg { + SetLatestRegistry { version: String, address: String }, +} + +#[cw_serde] +pub enum QueryMsg { + DecodeProto { + registry_version: Option, + query_id: String, + icq_result: InterchainQueryResult, + }, + GetKVKey { + registry_version: Option, + params: BTreeMap, + }, + ToCanonical {}, + FromCanonical {}, +} #[cw_serde] -pub enum QueryMsg {} +pub struct Broker { + // address of the instantiated registry + pub registry_address: Addr, + // semver + pub version: String, +} diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index a8aad41d..6df01af4 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -10,16 +10,17 @@ use neutron_sdk::{ pub mod broker; pub mod canonical_types; +pub mod type_registry; pub trait IcqIntegration { - fn get_kv_key(&self, params: BTreeMap) -> Result; + fn get_kv_key(params: BTreeMap) -> Result; fn decode_and_reconstruct( query_id: String, icq_result: InterchainQueryResult, ) -> Result; } -#[derive(Error, Debug, PartialEq)] +#[derive(Error, Debug)] pub enum MiddlewareError { #[error("{0}")] Std(#[from] StdError), @@ -27,11 +28,14 @@ pub enum MiddlewareError { #[error("{0}")] ParseIntError(#[from] std::num::ParseIntError), - #[error("{0}")] - DecodeError(#[from] prost::DecodeError), + #[error("failed to decode proto: {0}")] + DecodeError(String), #[error("{0}")] NeutronError(#[from] NeutronError), + + #[error("{0}")] + SemverError(#[from] semver::Error), } pub fn try_unpack_domain_specific_value( diff --git a/packages/middleware-utils/src/type_registry/mod.rs b/packages/middleware-utils/src/type_registry/mod.rs new file mode 100644 index 00000000..cd408564 --- /dev/null +++ b/packages/middleware-utils/src/type_registry/mod.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs new file mode 100644 index 00000000..f8cb7090 --- /dev/null +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -0,0 +1,42 @@ +use std::collections::BTreeMap; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Binary; +use neutron_sdk::bindings::types::InterchainQueryResult; + +use crate::canonical_types::{bank::balance::ValenceBankBalance, pools::xyk::ValenceXykPool}; + +#[cw_serde] +pub struct RegistryInstantiateMsg {} +#[cw_serde] +pub enum RegistryExecuteMsg {} + +#[cw_serde] +pub enum ValenceType { + XykPool(ValenceXykPool), + BankBalance(ValenceBankBalance), +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum RegistryQueryMsg { + /// serialize a message to binary + #[returns(Binary)] + Serialize { obj: ValenceType }, + /// deserialize a message from binary/bytes + #[returns(Binary)] + Deserialize { type_url: String, binary: Binary }, + + /// get the kvkey used for registering an interchain query + #[returns(Binary)] + KVKey { + type_id: String, + params: BTreeMap, + }, + + #[returns(Binary)] + ReconstructProto { + query_id: String, + icq_result: InterchainQueryResult, + }, // TODO: transform an outdated type to a new version +} From 28caad392ad201899272cea7c6ed6233d2fa4580 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 17:06:15 +0100 Subject: [PATCH 77/92] replace individual type adapters with ValenceTypeAdapter --- .../bank_balance/valence_adapter.rs | 37 ++++++---- .../src/definitions/gamm_pool/mod.rs | 11 ++- .../definitions/gamm_pool/valence_adapter.rs | 67 +++++++++++++------ .../osmo-26-0-0/src/definitions/mod.rs | 5 -- .../src/canonical_types/bank/balance.rs | 10 --- .../src/canonical_types/mod.rs | 9 +++ .../src/canonical_types/pools/xyk.rs | 9 --- 7 files changed, 87 insertions(+), 61 deletions(-) diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs index 8ec27d61..91d7d177 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs @@ -2,23 +2,24 @@ use cosmwasm_std::{coins, StdError}; use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; use osmosis_std::types::cosmos::base::v1beta1::Coin as ProtoCoin; use valence_middleware_utils::{ - canonical_types::bank::balance::{ValenceBankBalance, ValenceBankBalanceAdapter}, + canonical_types::{bank::balance::ValenceBankBalance, ValenceTypeAdapter}, + type_registry::types::ValenceType, MiddlewareError, }; use super::OsmosisBankBalance; -impl ValenceBankBalanceAdapter for OsmosisBankBalance { +impl ValenceTypeAdapter for OsmosisBankBalance { type External = QueryBalanceResponse; - fn try_to_canonical(&self) -> Result { + fn try_to_canonical(&self) -> Result { match &self.0.balance { Some(coin) => { let amount_u128 = coin.amount.parse::()?; - Ok(ValenceBankBalance { + Ok(ValenceType::BankBalance(ValenceBankBalance { assets: coins(amount_u128, coin.denom.to_string()), - }) + })) } None => Err(MiddlewareError::Std(StdError::generic_err( "failed to find coin in QueryBalanceResponse", @@ -26,9 +27,15 @@ impl ValenceBankBalanceAdapter for OsmosisBankBalance { } } - fn try_from_canonical( - canonical: ValenceBankBalance, - ) -> Result { + fn try_from_canonical(canonical: ValenceType) -> Result { + let canonical = match canonical { + ValenceType::BankBalance(b) => b, + _ => { + return Err(MiddlewareError::Std(StdError::generic_err( + "failed to convert ValenceType into QueryBalanceResponse", + ))) + } + }; let balance: Option = match canonical.assets.len() { 0 => None, 1 => { @@ -51,17 +58,18 @@ mod tests { use osmosis_std::types::cosmos::{ bank::v1beta1::QueryBalanceResponse, base::v1beta1::Coin as ProtoCoin, }; - use valence_middleware_utils::canonical_types::bank::balance::{ - ValenceBankBalance, ValenceBankBalanceAdapter, + use valence_middleware_utils::{ + canonical_types::{bank::balance::ValenceBankBalance, ValenceTypeAdapter}, + type_registry::types::ValenceType, }; use crate::definitions::bank_balance::OsmosisBankBalance; #[test] fn test_try_from_canonical() { - let canonical = ValenceBankBalance { + let canonical = ValenceType::BankBalance(ValenceBankBalance { assets: coins(100, "uosmo"), - }; + }); let result = OsmosisBankBalance::try_from_canonical(canonical).unwrap(); let result_coin = result.balance.unwrap(); @@ -80,6 +88,11 @@ mod tests { let result = osmosis_bank_balance.try_to_canonical().unwrap(); + let result = match result { + ValenceType::BankBalance(b) => b, + _ => panic!("unexpected result"), + }; + assert_eq!(result.assets.len(), 1); assert_eq!(result.assets[0].amount.u128(), 100); assert_eq!(result.assets[0].denom, "uosmo"); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs index 0fc30ecf..14d305dc 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs @@ -19,7 +19,7 @@ mod tests { use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; use osmosis_std::types::osmosis::gamm::v1beta1::Pool; use valence_middleware_utils::{ - canonical_types::pools::xyk::ValenceXykAdapter, IcqIntegration, + canonical_types::ValenceTypeAdapter, type_registry::types::ValenceType, IcqIntegration, }; use crate::definitions::gamm_pool::{OsmosisXykPool, STORAGE_PREFIX}; @@ -54,7 +54,12 @@ mod tests { // parse the external type into a valence type - let mut valence_pool = OsmosisXykPool(osmo_pool).try_to_canonical().unwrap(); + let canonical_valence_pool = OsmosisXykPool(osmo_pool).try_to_canonical().unwrap(); + + let mut valence_pool = match canonical_valence_pool.clone() { + ValenceType::XykPool(pool) => pool, + _ => panic!("unexpected type"), + }; // simulate modifying the pool instance valence_pool.assets.push(cosmwasm_std::coin(100, "batom")); @@ -64,7 +69,7 @@ mod tests { ); // convert the valence type back into the external type - let osmo_pool = OsmosisXykPool::try_from_canonical(valence_pool).unwrap(); + let osmo_pool = OsmosisXykPool::try_from_canonical(canonical_valence_pool).unwrap(); assert_eq!(osmo_pool.pool_assets.len(), 3); } diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs index 9a2188f6..41b7f01a 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs @@ -4,9 +4,12 @@ use std::str::FromStr; use cosmwasm_std::coin; use cosmwasm_std::to_json_binary; +use cosmwasm_std::StdError; use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; -use valence_middleware_utils::canonical_types::pools::xyk::{ValenceXykAdapter, ValenceXykPool}; +use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; +use valence_middleware_utils::canonical_types::ValenceTypeAdapter; +use valence_middleware_utils::type_registry::types::ValenceType; use valence_middleware_utils::{try_unpack_domain_specific_value, MiddlewareError}; use super::{ @@ -14,10 +17,10 @@ use super::{ SHARES_DENOM_KEY, TOTAL_WEIGHT_KEY, }; -impl ValenceXykAdapter for OsmosisXykPool { +impl ValenceTypeAdapter for OsmosisXykPool { type External = Pool; - fn try_to_canonical(&self) -> Result { + fn try_to_canonical(&self) -> Result { // pack all the domain-specific fields let mut domain_specific_fields = BTreeMap::from([ (ADDRESS_KEY.to_string(), to_json_binary(&self.0.address)?), @@ -64,46 +67,61 @@ impl ValenceXykAdapter for OsmosisXykPool { .map(|shares| shares.amount) .unwrap_or_default(); - Ok(ValenceXykPool { + Ok(ValenceType::XykPool(ValenceXykPool { assets, total_shares, domain_specific_fields, - }) + })) } - fn try_from_canonical(canonical: ValenceXykPool) -> Result { + fn try_from_canonical(canonical: ValenceType) -> Result { + let canonical_inner = match canonical { + ValenceType::XykPool(pool) => pool, + _ => { + return Err(MiddlewareError::Std(StdError::generic_err( + "canonical inner type mismatch", + ))) + } + }; // unpack the pool address let address: String = - try_unpack_domain_specific_value(ADDRESS_KEY, &canonical.domain_specific_fields)?; + try_unpack_domain_specific_value(ADDRESS_KEY, &canonical_inner.domain_specific_fields)?; // unpack the pool id - let id: u64 = try_unpack_domain_specific_value(ID_KEY, &canonical.domain_specific_fields)?; + let id: u64 = + try_unpack_domain_specific_value(ID_KEY, &canonical_inner.domain_specific_fields)?; // unpack the future pool governor let future_pool_governor: String = try_unpack_domain_specific_value( FUTURE_POOL_GOVERNOR_KEY, - &canonical.domain_specific_fields, + &canonical_inner.domain_specific_fields, )?; // unpack the pool params - let pool_params: Option = - try_unpack_domain_specific_value(POOL_PARAMS_KEY, &canonical.domain_specific_fields)?; + let pool_params: Option = try_unpack_domain_specific_value( + POOL_PARAMS_KEY, + &canonical_inner.domain_specific_fields, + )?; // unpack the shares denom and total shares amount before combining them to a proto coin - let shares_denom: String = - try_unpack_domain_specific_value(SHARES_DENOM_KEY, &canonical.domain_specific_fields)?; + let shares_denom: String = try_unpack_domain_specific_value( + SHARES_DENOM_KEY, + &canonical_inner.domain_specific_fields, + )?; let shares_coin = Coin { denom: shares_denom, - amount: canonical.total_shares, + amount: canonical_inner.total_shares, }; // unpack the total weight - let total_weight: String = - try_unpack_domain_specific_value(TOTAL_WEIGHT_KEY, &canonical.domain_specific_fields)?; + let total_weight: String = try_unpack_domain_specific_value( + TOTAL_WEIGHT_KEY, + &canonical_inner.domain_specific_fields, + )?; // unpack the pool assets let mut pool_assets = vec![]; - for asset in &canonical.assets { + for asset in &canonical_inner.assets { let pool_asset = PoolAsset { token: Some(Coin { denom: asset.denom.to_string(), @@ -111,7 +129,7 @@ impl ValenceXykAdapter for OsmosisXykPool { }), weight: try_unpack_domain_specific_value( &format!("pool_asset_{}_weight", asset.denom), - &canonical.domain_specific_fields, + &canonical_inner.domain_specific_fields, )?, }; pool_assets.push(pool_asset); @@ -169,11 +187,11 @@ mod tests { (TOTAL_WEIGHT_KEY.to_string(), to_json_binary("100").unwrap()), ]); - let pool = ValenceXykPool { + let pool = ValenceType::XykPool(ValenceXykPool { assets: vec![coin(100, "uatom"), coin(200, "uosmo")], total_shares: "1000".to_string(), domain_specific_fields, - }; + }); let osmosis_pool = OsmosisXykPool::try_from_canonical(pool).unwrap(); @@ -225,8 +243,13 @@ mod tests { total_weight: "100".to_string(), }; - let valence_xyk_pool = OsmosisXykPool(pool).try_to_canonical().unwrap(); - println!("parsed xyk pool: {:?}", valence_xyk_pool); + let canonical_valence_xyk_pool = OsmosisXykPool(pool).try_to_canonical().unwrap(); + println!("parsed xyk pool: {:?}", canonical_valence_xyk_pool); + + let valence_xyk_pool = match canonical_valence_xyk_pool { + ValenceType::XykPool(pool) => pool, + _ => panic!("unexpected type"), + }; assert_eq!(valence_xyk_pool.assets.len(), 2); assert_eq!(valence_xyk_pool.assets[0], coin(100, "uatom")); diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs index a6f06a52..02796673 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -1,8 +1,3 @@ -use cosmwasm_schema::cw_serde; -use valence_middleware_utils::canonical_types::{ - bank::balance::ValenceBankBalance, pools::xyk::ValenceXykPool, -}; - pub mod bank_balance; pub mod gamm_pool; diff --git a/packages/middleware-utils/src/canonical_types/bank/balance.rs b/packages/middleware-utils/src/canonical_types/bank/balance.rs index 1ea9e455..30dd1863 100644 --- a/packages/middleware-utils/src/canonical_types/bank/balance.rs +++ b/packages/middleware-utils/src/canonical_types/bank/balance.rs @@ -1,16 +1,6 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::Coin; -use crate::MiddlewareError; - -pub trait ValenceBankBalanceAdapter { - type External; - - fn try_to_canonical(&self) -> Result; - fn try_from_canonical(canonical: ValenceBankBalance) - -> Result; -} - #[cw_serde] pub struct ValenceBankBalance { pub assets: Vec, diff --git a/packages/middleware-utils/src/canonical_types/mod.rs b/packages/middleware-utils/src/canonical_types/mod.rs index 50e49e71..1d841a23 100644 --- a/packages/middleware-utils/src/canonical_types/mod.rs +++ b/packages/middleware-utils/src/canonical_types/mod.rs @@ -1,2 +1,11 @@ +use crate::{type_registry::types::ValenceType, MiddlewareError}; + pub mod bank; pub mod pools; + +pub trait ValenceTypeAdapter { + type External; + + fn try_to_canonical(&self) -> Result; + fn try_from_canonical(canonical: ValenceType) -> Result; +} diff --git a/packages/middleware-utils/src/canonical_types/pools/xyk.rs b/packages/middleware-utils/src/canonical_types/pools/xyk.rs index ed6216b2..35fd1ffd 100644 --- a/packages/middleware-utils/src/canonical_types/pools/xyk.rs +++ b/packages/middleware-utils/src/canonical_types/pools/xyk.rs @@ -3,15 +3,6 @@ use std::collections::BTreeMap; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ensure, Binary, Coin, Decimal, StdError, StdResult}; -use crate::MiddlewareError; - -pub trait ValenceXykAdapter { - type External; - - fn try_to_canonical(&self) -> Result; - fn try_from_canonical(canonical: ValenceXykPool) -> Result; -} - #[cw_serde] pub struct ValenceXykPool { /// assets in the pool From f293e04782069f7a939fb2086ef00e92f1cc5c0e Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 19:05:10 +0100 Subject: [PATCH 78/92] testing mod in broker; integrate kv_key & proto_reconstruct carryover queries --- Cargo.lock | 3 +- Cargo.toml | 1 - .../middleware/brokers/osmo-broker/Cargo.toml | 3 +- .../brokers/osmo-broker/src/contract.rs | 28 +++-- .../middleware/brokers/osmo-broker/src/lib.rs | 3 + .../brokers/osmo-broker/src/testing/mod.rs | 111 ++++++++++++++++++ .../brokers/osmo-broker/src/testing/tests.rs | 49 ++++++++ .../osmosis/osmo-26-0-0/src/contract.rs | 7 +- packages/middleware-utils/src/broker/types.rs | 10 +- .../src/type_registry/types.rs | 12 +- 10 files changed, 210 insertions(+), 17 deletions(-) create mode 100644 contracts/middleware/brokers/osmo-broker/src/testing/mod.rs create mode 100644 contracts/middleware/brokers/osmo-broker/src/testing/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 8ff12b10..f4636efc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5314,18 +5314,19 @@ version = "0.1.0" dependencies = [ "cosmwasm-schema 2.1.4", "cosmwasm-std 2.1.4", + "cw-multi-test", "cw-ownable", "cw-storage-plus 2.0.0", "neutron-sdk", "osmosis-std", "osmosis-std-derive", - "osmosis-test-tube", "prost 0.13.3", "prost-types 0.13.3", "semver", "serde-json-wasm 1.0.1", "serde_json", "thiserror 1.0.69", + "valence-middleware-osmosis", "valence-middleware-utils", ] diff --git a/Cargo.toml b/Cargo.toml index e845e36c..3f992222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,7 +96,6 @@ valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } valence-icq-lib-utils = { path = "packages/icq-querier-utils" } valence-middleware-utils = { path = "packages/middleware-utils" } -# valence-canonical-types = { path = "packages/canonical-types" } # domain type registries valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } diff --git a/contracts/middleware/brokers/osmo-broker/Cargo.toml b/contracts/middleware/brokers/osmo-broker/Cargo.toml index 60168218..229800c1 100644 --- a/contracts/middleware/brokers/osmo-broker/Cargo.toml +++ b/contracts/middleware/brokers/osmo-broker/Cargo.toml @@ -30,4 +30,5 @@ valence-middleware-utils = { workspace = true } semver = { workspace = true } [dev-dependencies] -osmosis-test-tube = { workspace = true } +cw-multi-test = { workspace = true } +valence-middleware-osmosis = { workspace = true } diff --git a/contracts/middleware/brokers/osmo-broker/src/contract.rs b/contracts/middleware/brokers/osmo-broker/src/contract.rs index c62fe92b..6779428e 100644 --- a/contracts/middleware/brokers/osmo-broker/src/contract.rs +++ b/contracts/middleware/brokers/osmo-broker/src/contract.rs @@ -2,12 +2,12 @@ use std::{collections::BTreeMap, str::FromStr}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; -use neutron_sdk::bindings::types::InterchainQueryResult; +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use semver::Version; use valence_middleware_utils::{ broker::types::{Broker, ExecuteMsg, InstantiateMsg, QueryMsg}, - type_registry::types::RegistryQueryMsg, + type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}, MiddlewareError, }; @@ -70,8 +70,9 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { } => try_decode_proto(deps, registry_version, query_id, icq_result), QueryMsg::GetKVKey { registry_version, + query_id, params, - } => try_get_kv_key(deps, registry_version, params), + } => try_get_kv_key(deps, registry_version, query_id, params), QueryMsg::ToCanonical {} => try_to_canonical(), QueryMsg::FromCanonical {} => try_from_canonical(), } @@ -85,7 +86,7 @@ fn try_decode_proto( ) -> StdResult { let target_registry = get_target_registry(deps, registry_version)?; - let decoded_result = deps.querier.query_wasm_smart( + let resp: NativeTypeWrapper = deps.querier.query_wasm_smart( target_registry.registry_address, &RegistryQueryMsg::ReconstructProto { query_id, @@ -93,17 +94,25 @@ fn try_decode_proto( }, )?; - Ok(decoded_result) + to_json_binary(&resp) } fn try_get_kv_key( deps: Deps, registry_version: Option, + type_id: String, params: BTreeMap, ) -> StdResult { let target_registry = get_target_registry(deps, registry_version)?; - Ok(Binary::new("a".as_bytes().to_vec())) + let response: KVKey = deps.querier.query_wasm_smart( + target_registry.registry_address, + &RegistryQueryMsg::KVKey { type_id, params }, + )?; + + println!("[broker] response kv key: {:?}", response); + + to_json_binary(&response) } fn try_to_canonical() -> StdResult { @@ -121,5 +130,8 @@ fn get_target_registry(deps: Deps, version: Option) -> StdResult None => LATEST.load(deps.storage)?, }; // load the target registry - ACTIVE_REGISTRIES.load(deps.storage, target_version) + let registry = ACTIVE_REGISTRIES.load(deps.storage, target_version)?; + println!("[broker] target registry: {:?}", registry.registry_address); + + Ok(registry) } diff --git a/contracts/middleware/brokers/osmo-broker/src/lib.rs b/contracts/middleware/brokers/osmo-broker/src/lib.rs index 3407c199..fea2cb87 100644 --- a/contracts/middleware/brokers/osmo-broker/src/lib.rs +++ b/contracts/middleware/brokers/osmo-broker/src/lib.rs @@ -1,2 +1,5 @@ pub mod contract; pub mod state; + +#[cfg(test)] +mod testing; diff --git a/contracts/middleware/brokers/osmo-broker/src/testing/mod.rs b/contracts/middleware/brokers/osmo-broker/src/testing/mod.rs new file mode 100644 index 00000000..34eb5e1e --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/src/testing/mod.rs @@ -0,0 +1,111 @@ +pub mod tests; + +use std::collections::BTreeMap; + +use cosmwasm_std::{Addr, Binary, StdResult}; +use cw_multi_test::{App, AppResponse, ContractWrapper, Executor}; +use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; +use valence_middleware_utils::{broker::types::QueryMsg, type_registry::types::NativeTypeWrapper}; + +struct Suite { + pub app: App, + pub owner: Addr, + pub broker_addr: Addr, + pub registry_addr: Addr, +} + +impl Default for Suite { + fn default() -> Self { + let mut app = App::default(); + + let owner = app.api().addr_make("owner"); + + let broker_wrapper = ContractWrapper::new( + crate::contract::execute, + crate::contract::instantiate, + crate::contract::query, + ); + let registry_wrapper = ContractWrapper::new( + valence_middleware_osmosis::contract::execute, + valence_middleware_osmosis::contract::instantiate, + valence_middleware_osmosis::contract::query, + ); + + let broker_code_id = app.store_code(Box::new(broker_wrapper)); + let registry_code_id = app.store_code(Box::new(registry_wrapper)); + + let broker_instantiate_msg = valence_middleware_utils::broker::types::InstantiateMsg {}; + let registry_instantiate_msg = + valence_middleware_utils::type_registry::types::RegistryInstantiateMsg {}; + + let broker_addr = app + .instantiate_contract( + broker_code_id, + owner.clone(), + &broker_instantiate_msg, + &[], + "osmo_broker".to_string(), + None, + ) + .unwrap(); + + let registry_addr = app + .instantiate_contract( + registry_code_id, + owner.clone(), + ®istry_instantiate_msg, + &[], + "osmo_registry".to_string(), + None, + ) + .unwrap(); + + Suite { + app, + owner, + broker_addr, + registry_addr, + } + } +} + +impl Suite { + fn add_new_registry(&mut self, version: &str, addr: String) -> AppResponse { + let msg = valence_middleware_utils::broker::types::ExecuteMsg::SetLatestRegistry { + version: version.to_string(), + address: addr, + }; + + self.app + .execute_contract(self.owner.clone(), self.broker_addr.clone(), &msg, &[]) + .unwrap() + } + + fn query_decode_proto( + &mut self, + query_id: &str, + icq_result: InterchainQueryResult, + ) -> StdResult { + let msg = valence_middleware_utils::broker::types::QueryMsg::DecodeProto { + registry_version: None, + query_id: query_id.to_string(), + icq_result, + }; + + self.app + .wrap() + .query_wasm_smart(self.broker_addr.clone(), &msg) + } + + fn get_kv_key(&mut self, query_id: &str, params: BTreeMap) -> StdResult { + let msg = QueryMsg::GetKVKey { + registry_version: None, + query_id: query_id.to_string(), + params, + }; + + self.app + .wrap() + .query_wasm_smart(self.broker_addr.clone(), &msg) + } +} diff --git a/contracts/middleware/brokers/osmo-broker/src/testing/tests.rs b/contracts/middleware/brokers/osmo-broker/src/testing/tests.rs new file mode 100644 index 00000000..ae0a1b57 --- /dev/null +++ b/contracts/middleware/brokers/osmo-broker/src/testing/tests.rs @@ -0,0 +1,49 @@ +use std::collections::BTreeMap; + +use cosmwasm_std::{to_json_binary, Binary}; +use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; + +use super::Suite; + +#[test] +fn test_init() { + let mut suite = Suite::default(); + + let resp = suite.add_new_registry("1.0.0", suite.registry_addr.to_string()); + + println!("resp: {:?}", resp); + + let params = BTreeMap::from([("pool_id".to_string(), to_json_binary(&1u64).unwrap())]); + + let kv_key = suite.get_kv_key("gamm_pool", params).unwrap(); + + println!("kv_key: {:?}", kv_key); +} + +#[test] +fn test_reconstruct_proto() { + let mut suite = Suite::default(); + + suite.add_new_registry("1.0.0", suite.registry_addr.to_string()); + + let b64_key = "AgAAAAAAAAAB"; + let binary_key = Binary::from_base64(b64_key).unwrap(); + + let b64_value = "Chovb3Ntb3Npcy5nYW1tLnYxYmV0YTEuUG9vbBKGAgo/b3NtbzE5ZTJtZjdjeXdrdjd6YXVnNm5rNWY4N2QwN2Z4cmRncmxhZHZ5bWgyZ3d2NWNydm0zdm5zdWV3aGg3EAEaBgoBMBIBMCIEMTI4aCokCgtnYW1tL3Bvb2wvMRIVMTAwMDAwMDAwMDAwMDAwMDAwMDAwMl8KUQpEaWJjLzRFNDFFRDhGM0RDQUVBMTVGNEQ2QURDNkVERDdDMDRBNjc2MTYwNzM1Qzk3MTBCOTA0QjdCRjUzNTI1QjU2RDYSCTEwMDAwMDAwMBIKMTA3Mzc0MTgyNDIgChIKBXVvc21vEgkxMDAwMDAwMDASCjEwNzM3NDE4MjQ6CjIxNDc0ODM2NDg="; + let binary_value = Binary::from_base64(b64_value).unwrap(); + + let storage_value = StorageValue { + storage_prefix: "gamm".to_string(), + key: binary_key, + value: binary_value, + }; + + let icq_result = InterchainQueryResult { + kv_results: vec![storage_value], + height: 1, + revision: 1, + }; + + let reconstructed_result = suite.query_decode_proto("gamm_pool", icq_result).unwrap(); + println!("reconstructed result: {:?}", reconstructed_result); +} diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 7759a5c3..71d319dd 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -9,7 +9,8 @@ use neutron_sdk::bindings::types::InterchainQueryResult; use valence_middleware_utils::{ canonical_types::pools::xyk::ValenceXykPool, type_registry::types::{ - RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, ValenceType, + NativeTypeWrapper, RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, + ValenceType, }, IcqIntegration, }; @@ -63,6 +64,8 @@ fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResul _ => return Err(StdError::generic_err("unknown type_id")), }; + println!("[registry] kv key: {:?}", kv_key); + match kv_key { Ok(kv) => to_json_binary(&kv), Err(_) => Err(StdError::generic_err("failed to read kv key")), @@ -77,7 +80,7 @@ fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> }; match reconstruction_result { - Ok(res) => to_json_binary(&res), + Ok(res) => to_json_binary(&NativeTypeWrapper { binary: res }), Err(_) => Err(StdError::generic_err( "failed to reconstruct type from proto", )), diff --git a/packages/middleware-utils/src/broker/types.rs b/packages/middleware-utils/src/broker/types.rs index 71c9a07c..3c5e1b8b 100644 --- a/packages/middleware-utils/src/broker/types.rs +++ b/packages/middleware-utils/src/broker/types.rs @@ -1,9 +1,11 @@ use std::collections::BTreeMap; -use cosmwasm_schema::cw_serde; +use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Binary}; use neutron_sdk::bindings::types::InterchainQueryResult; +use crate::type_registry::types::{NativeTypeWrapper, ValenceType}; + #[cw_serde] pub struct InstantiateMsg {} @@ -13,17 +15,23 @@ pub enum ExecuteMsg { } #[cw_serde] +#[derive(QueryResponses)] pub enum QueryMsg { + #[returns(NativeTypeWrapper)] DecodeProto { registry_version: Option, query_id: String, icq_result: InterchainQueryResult, }, + #[returns(neutron_sdk::bindings::types::KVKey)] GetKVKey { registry_version: Option, + query_id: String, params: BTreeMap, }, + #[returns(ValenceType)] ToCanonical {}, + #[returns(Binary)] FromCanonical {}, } diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index f8cb7090..757a3a66 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -28,15 +28,21 @@ pub enum RegistryQueryMsg { Deserialize { type_url: String, binary: Binary }, /// get the kvkey used for registering an interchain query - #[returns(Binary)] + #[returns(neutron_sdk::bindings::types::KVKey)] KVKey { type_id: String, params: BTreeMap, }, - #[returns(Binary)] + #[returns(NativeTypeWrapper)] ReconstructProto { query_id: String, icq_result: InterchainQueryResult, - }, // TODO: transform an outdated type to a new version + }, + // TODO: transform an outdated type to a new version +} + +#[cw_serde] +pub struct NativeTypeWrapper { + pub binary: Binary, } From 007d2dc6b80cf277085510dd9c32ecda24013a54 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 21:33:19 +0100 Subject: [PATCH 79/92] cleanup broker --- Cargo.lock | 4 +- Cargo.toml | 6 +-- .../osmo-broker => broker}/.cargo/config.toml | 0 .../osmo-broker => broker}/Cargo.toml | 4 +- contracts/middleware/broker/README.md | 49 +++++++++++++++++++ .../osmo-broker => broker}/src/contract.rs | 0 .../osmo-broker => broker}/src/lib.rs | 0 .../osmo-broker => broker}/src/state.rs | 0 .../osmo-broker => broker}/src/testing/mod.rs | 0 .../src/testing/tests.rs | 0 .../middleware/brokers/osmo-broker/README.md | 0 11 files changed, 54 insertions(+), 9 deletions(-) rename contracts/middleware/{brokers/osmo-broker => broker}/.cargo/config.toml (100%) rename contracts/middleware/{brokers/osmo-broker => broker}/Cargo.toml (89%) create mode 100644 contracts/middleware/broker/README.md rename contracts/middleware/{brokers/osmo-broker => broker}/src/contract.rs (100%) rename contracts/middleware/{brokers/osmo-broker => broker}/src/lib.rs (100%) rename contracts/middleware/{brokers/osmo-broker => broker}/src/state.rs (100%) rename contracts/middleware/{brokers/osmo-broker => broker}/src/testing/mod.rs (100%) rename contracts/middleware/{brokers/osmo-broker => broker}/src/testing/tests.rs (100%) delete mode 100644 contracts/middleware/brokers/osmo-broker/README.md diff --git a/Cargo.lock b/Cargo.lock index f4636efc..f43cd980 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5309,7 +5309,7 @@ dependencies = [ ] [[package]] -name = "valence-middleware-broker-osmosis" +name = "valence-middleware-broker" version = "0.1.0" dependencies = [ "cosmwasm-schema 2.1.4", @@ -5318,8 +5318,6 @@ dependencies = [ "cw-ownable", "cw-storage-plus 2.0.0", "neutron-sdk", - "osmosis-std", - "osmosis-std-derive", "prost 0.13.3", "prost-types 0.13.3", "semver", diff --git a/Cargo.toml b/Cargo.toml index 3f992222..18990f34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ "contracts/testing/*", "contracts/program-registry", "contracts/middleware/domains/osmosis/osmo-26-0-0", - "contracts/middleware/brokers/osmo-broker", + "contracts/middleware/broker", "packages/*", "program-manager", "local-interchaintest", @@ -77,8 +77,8 @@ valence-osmosis-cl-withdrawer = { path = "contracts/libraries/osmosis-cl- valence-icq-querier = { path = "contracts/libraries/icq-querier", features = ["library"] } # middleware -valence-middleware-osmosis = { path = "contracts/middleware/domains/osmosis/osmo-26-0-0", features = ["library"] } -valence-middleware-broker-osmosis = { path = "contracts/middleware/brokers/osmo-broker", features = ["library"] } +valence-middleware-osmosis = { path = "contracts/middleware/domains/osmosis/osmo-26-0-0", features = ["library"] } +valence-middleware-broker = { path = "contracts/middleware/brokers", features = ["library"] } # our packages valence-account-utils = { path = "packages/account-utils" } diff --git a/contracts/middleware/brokers/osmo-broker/.cargo/config.toml b/contracts/middleware/broker/.cargo/config.toml similarity index 100% rename from contracts/middleware/brokers/osmo-broker/.cargo/config.toml rename to contracts/middleware/broker/.cargo/config.toml diff --git a/contracts/middleware/brokers/osmo-broker/Cargo.toml b/contracts/middleware/broker/Cargo.toml similarity index 89% rename from contracts/middleware/brokers/osmo-broker/Cargo.toml rename to contracts/middleware/broker/Cargo.toml index 229800c1..70887b8e 100644 --- a/contracts/middleware/brokers/osmo-broker/Cargo.toml +++ b/contracts/middleware/broker/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "valence-middleware-broker-osmosis" +name = "valence-middleware-broker" authors = { workspace = true } edition = { workspace = true } license = { workspace = true } @@ -17,8 +17,6 @@ library = [] cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } cw-ownable = { workspace = true } -osmosis-std = "0.26.0" -osmosis-std-derive = "0.26.0" prost = { workspace = true } prost-types = { workspace = true } neutron-sdk = { workspace = true } diff --git a/contracts/middleware/broker/README.md b/contracts/middleware/broker/README.md new file mode 100644 index 00000000..cad644b7 --- /dev/null +++ b/contracts/middleware/broker/README.md @@ -0,0 +1,49 @@ +# Middleware Brokers + +*Middleware brokers* are the gateway to using the Valence Type +system. + +Brokers are responsible for offering a unified interface for +domain-specific type access. + +Given that, every broker is a singleton component responsible +for unifying a particular set of types. + +Because a broker offers a single interface for all types, programs +relying on those types only need to know about the broker in order +to access them. + +## Broker lifecycle + +Brokers are singleton components that are instantiated before the +program start time. For that reason, it is important to ensure that +brokers are up to date and remains to be valid throughout the program +lifecycle. + +This up-to-date property is achieved by enabling brokers to be updated +during runtime: once the broker is instantiated, it can be updated by +adding new registries. + +## Adding new registries + +Registries can be added by calling the following execute method: +```rust +AddRegistry { + // semver string + version: String, + // address of the registry managing the types + address: String +} +``` + +This will store the latest registry information in the broker state, +allowing it to grow dynamically. + +Registries are indexed by their associated versions. Registering the +same `semver` key will overwrite the previous registry. + +## API + +Broker API is neutral and must remain compatible with all type registries. + +This is done by wrapping around the registry api defined in `middleware-utils`. diff --git a/contracts/middleware/brokers/osmo-broker/src/contract.rs b/contracts/middleware/broker/src/contract.rs similarity index 100% rename from contracts/middleware/brokers/osmo-broker/src/contract.rs rename to contracts/middleware/broker/src/contract.rs diff --git a/contracts/middleware/brokers/osmo-broker/src/lib.rs b/contracts/middleware/broker/src/lib.rs similarity index 100% rename from contracts/middleware/brokers/osmo-broker/src/lib.rs rename to contracts/middleware/broker/src/lib.rs diff --git a/contracts/middleware/brokers/osmo-broker/src/state.rs b/contracts/middleware/broker/src/state.rs similarity index 100% rename from contracts/middleware/brokers/osmo-broker/src/state.rs rename to contracts/middleware/broker/src/state.rs diff --git a/contracts/middleware/brokers/osmo-broker/src/testing/mod.rs b/contracts/middleware/broker/src/testing/mod.rs similarity index 100% rename from contracts/middleware/brokers/osmo-broker/src/testing/mod.rs rename to contracts/middleware/broker/src/testing/mod.rs diff --git a/contracts/middleware/brokers/osmo-broker/src/testing/tests.rs b/contracts/middleware/broker/src/testing/tests.rs similarity index 100% rename from contracts/middleware/brokers/osmo-broker/src/testing/tests.rs rename to contracts/middleware/broker/src/testing/tests.rs diff --git a/contracts/middleware/brokers/osmo-broker/README.md b/contracts/middleware/brokers/osmo-broker/README.md deleted file mode 100644 index e69de29b..00000000 From 6af35913271fcc4a8bc1668ad6af52f6542dd436 Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 21:40:50 +0100 Subject: [PATCH 80/92] remove broker utils by moving logic into broker --- contracts/middleware/broker/src/contract.rs | 12 +++++++----- contracts/middleware/broker/src/lib.rs | 1 + .../middleware/broker/src/msg.rs | 5 ++--- contracts/middleware/broker/src/state.rs | 5 +++-- contracts/middleware/broker/src/testing/mod.rs | 10 ++++++---- packages/middleware-utils/src/broker/mod.rs | 1 - packages/middleware-utils/src/lib.rs | 1 - 7 files changed, 19 insertions(+), 16 deletions(-) rename packages/middleware-utils/src/broker/types.rs => contracts/middleware/broker/src/msg.rs (89%) delete mode 100644 packages/middleware-utils/src/broker/mod.rs diff --git a/contracts/middleware/broker/src/contract.rs b/contracts/middleware/broker/src/contract.rs index 6779428e..4c282883 100644 --- a/contracts/middleware/broker/src/contract.rs +++ b/contracts/middleware/broker/src/contract.rs @@ -6,12 +6,14 @@ use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Resp use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use semver::Version; use valence_middleware_utils::{ - broker::types::{Broker, ExecuteMsg, InstantiateMsg, QueryMsg}, type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}, MiddlewareError, }; -use crate::state::{ACTIVE_REGISTRIES, LATEST}; +use crate::{ + msg::{ExecuteMsg, InstantiateMsg, QueryMsg, TypeRegistry}, + state::{ACTIVE_REGISTRIES, LATEST}, +}; // version info for migration info const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); @@ -49,12 +51,12 @@ fn try_add_new_registry( let addr = deps.api.addr_validate(&addr)?; let version = Version::from_str(&version)?; - let broker = Broker { + let type_registry = TypeRegistry { registry_address: addr, version: version.to_string(), }; - ACTIVE_REGISTRIES.save(deps.storage, version.to_string(), &broker)?; + ACTIVE_REGISTRIES.save(deps.storage, version.to_string(), &type_registry)?; LATEST.save(deps.storage, &version.to_string())?; Ok(Response::new()) @@ -123,7 +125,7 @@ fn try_from_canonical() -> StdResult { Ok(Binary::new("a".as_bytes().to_vec())) } -fn get_target_registry(deps: Deps, version: Option) -> StdResult { +fn get_target_registry(deps: Deps, version: Option) -> StdResult { // if version is specified, we use that. otherwise default to latest. let target_version = match version { Some(version) => version, diff --git a/contracts/middleware/broker/src/lib.rs b/contracts/middleware/broker/src/lib.rs index fea2cb87..ffa4f024 100644 --- a/contracts/middleware/broker/src/lib.rs +++ b/contracts/middleware/broker/src/lib.rs @@ -1,4 +1,5 @@ pub mod contract; +pub mod msg; pub mod state; #[cfg(test)] diff --git a/packages/middleware-utils/src/broker/types.rs b/contracts/middleware/broker/src/msg.rs similarity index 89% rename from packages/middleware-utils/src/broker/types.rs rename to contracts/middleware/broker/src/msg.rs index 3c5e1b8b..cb412b01 100644 --- a/packages/middleware-utils/src/broker/types.rs +++ b/contracts/middleware/broker/src/msg.rs @@ -3,8 +3,7 @@ use std::collections::BTreeMap; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Binary}; use neutron_sdk::bindings::types::InterchainQueryResult; - -use crate::type_registry::types::{NativeTypeWrapper, ValenceType}; +use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, ValenceType}; #[cw_serde] pub struct InstantiateMsg {} @@ -36,7 +35,7 @@ pub enum QueryMsg { } #[cw_serde] -pub struct Broker { +pub struct TypeRegistry { // address of the instantiated registry pub registry_address: Addr, // semver diff --git a/contracts/middleware/broker/src/state.rs b/contracts/middleware/broker/src/state.rs index 47477fc2..9ba8d260 100644 --- a/contracts/middleware/broker/src/state.rs +++ b/contracts/middleware/broker/src/state.rs @@ -1,5 +1,6 @@ use cw_storage_plus::{Item, Map}; -use valence_middleware_utils::broker::types::Broker; -pub const ACTIVE_REGISTRIES: Map = Map::new("active_registries"); +use crate::msg::TypeRegistry; + +pub const ACTIVE_REGISTRIES: Map = Map::new("active_registries"); pub const LATEST: Item = Item::new("latest"); diff --git a/contracts/middleware/broker/src/testing/mod.rs b/contracts/middleware/broker/src/testing/mod.rs index 34eb5e1e..0241ca07 100644 --- a/contracts/middleware/broker/src/testing/mod.rs +++ b/contracts/middleware/broker/src/testing/mod.rs @@ -5,7 +5,9 @@ use std::collections::BTreeMap; use cosmwasm_std::{Addr, Binary, StdResult}; use cw_multi_test::{App, AppResponse, ContractWrapper, Executor}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; -use valence_middleware_utils::{broker::types::QueryMsg, type_registry::types::NativeTypeWrapper}; +use valence_middleware_utils::type_registry::types::NativeTypeWrapper; + +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; struct Suite { pub app: App, @@ -34,7 +36,7 @@ impl Default for Suite { let broker_code_id = app.store_code(Box::new(broker_wrapper)); let registry_code_id = app.store_code(Box::new(registry_wrapper)); - let broker_instantiate_msg = valence_middleware_utils::broker::types::InstantiateMsg {}; + let broker_instantiate_msg = InstantiateMsg {}; let registry_instantiate_msg = valence_middleware_utils::type_registry::types::RegistryInstantiateMsg {}; @@ -71,7 +73,7 @@ impl Default for Suite { impl Suite { fn add_new_registry(&mut self, version: &str, addr: String) -> AppResponse { - let msg = valence_middleware_utils::broker::types::ExecuteMsg::SetLatestRegistry { + let msg = ExecuteMsg::SetLatestRegistry { version: version.to_string(), address: addr, }; @@ -86,7 +88,7 @@ impl Suite { query_id: &str, icq_result: InterchainQueryResult, ) -> StdResult { - let msg = valence_middleware_utils::broker::types::QueryMsg::DecodeProto { + let msg = QueryMsg::DecodeProto { registry_version: None, query_id: query_id.to_string(), icq_result, diff --git a/packages/middleware-utils/src/broker/mod.rs b/packages/middleware-utils/src/broker/mod.rs deleted file mode 100644 index cd408564..00000000 --- a/packages/middleware-utils/src/broker/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod types; diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index 6df01af4..033b341c 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -8,7 +8,6 @@ use neutron_sdk::{ NeutronError, }; -pub mod broker; pub mod canonical_types; pub mod type_registry; From d5a5ad31f6f65a123bdad754ddc43ff58c00424f Mon Sep 17 00:00:00 2001 From: bekauz Date: Tue, 17 Dec 2024 22:13:49 +0100 Subject: [PATCH 81/92] simplify broker query logic by wrapping the type registry query msg --- contracts/middleware/broker/src/contract.rs | 65 +++++++++---------- contracts/middleware/broker/src/msg.rs | 32 ++------- .../middleware/broker/src/testing/mod.rs | 21 +++--- .../osmosis/osmo-26-0-0/src/contract.rs | 4 +- .../src/type_registry/types.rs | 4 +- 5 files changed, 53 insertions(+), 73 deletions(-) diff --git a/contracts/middleware/broker/src/contract.rs b/contracts/middleware/broker/src/contract.rs index 4c282883..df78fa63 100644 --- a/contracts/middleware/broker/src/contract.rs +++ b/contracts/middleware/broker/src/contract.rs @@ -37,7 +37,7 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { match msg { - ExecuteMsg::SetLatestRegistry { version, address } => { + ExecuteMsg::SetRegistry { version, address } => { try_add_new_registry(deps, version, address) } } @@ -56,6 +56,9 @@ fn try_add_new_registry( version: version.to_string(), }; + // TODO: likely here we will need to "couple" the new type + // with the previous one to know the type update route + ACTIVE_REGISTRIES.save(deps.storage, version.to_string(), &type_registry)?; LATEST.save(deps.storage, &version.to_string())?; @@ -64,32 +67,40 @@ fn try_add_new_registry( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::DecodeProto { - registry_version, + // if version is specified, we use that. otherwise default to latest. + let target_version = match msg.registry_version { + Some(version) => version, + None => LATEST.load(deps.storage)?, + }; + // load the target registry + let registry = ACTIVE_REGISTRIES.load(deps.storage, target_version)?; + + match msg.query { + RegistryQueryMsg::ReconstructProto { query_id, icq_result, - } => try_decode_proto(deps, registry_version, query_id, icq_result), - QueryMsg::GetKVKey { - registry_version, + } => try_decode_proto( + deps, + registry.registry_address.to_string(), query_id, - params, - } => try_get_kv_key(deps, registry_version, query_id, params), - QueryMsg::ToCanonical {} => try_to_canonical(), - QueryMsg::FromCanonical {} => try_from_canonical(), + icq_result, + ), + RegistryQueryMsg::KVKey { type_id, params } => { + try_get_kv_key(deps, registry.registry_address.to_string(), type_id, params) + } + RegistryQueryMsg::ToCanonical { type_url, binary } => try_to_canonical(), + RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(), } } fn try_decode_proto( deps: Deps, - registry_version: Option, + registry: String, query_id: String, icq_result: InterchainQueryResult, ) -> StdResult { - let target_registry = get_target_registry(deps, registry_version)?; - let resp: NativeTypeWrapper = deps.querier.query_wasm_smart( - target_registry.registry_address, + registry, &RegistryQueryMsg::ReconstructProto { query_id, icq_result, @@ -101,16 +112,13 @@ fn try_decode_proto( fn try_get_kv_key( deps: Deps, - registry_version: Option, + registry: String, type_id: String, params: BTreeMap, ) -> StdResult { - let target_registry = get_target_registry(deps, registry_version)?; - - let response: KVKey = deps.querier.query_wasm_smart( - target_registry.registry_address, - &RegistryQueryMsg::KVKey { type_id, params }, - )?; + let response: KVKey = deps + .querier + .query_wasm_smart(registry, &RegistryQueryMsg::KVKey { type_id, params })?; println!("[broker] response kv key: {:?}", response); @@ -124,16 +132,3 @@ fn try_to_canonical() -> StdResult { fn try_from_canonical() -> StdResult { Ok(Binary::new("a".as_bytes().to_vec())) } - -fn get_target_registry(deps: Deps, version: Option) -> StdResult { - // if version is specified, we use that. otherwise default to latest. - let target_version = match version { - Some(version) => version, - None => LATEST.load(deps.storage)?, - }; - // load the target registry - let registry = ACTIVE_REGISTRIES.load(deps.storage, target_version)?; - println!("[broker] target registry: {:?}", registry.registry_address); - - Ok(registry) -} diff --git a/contracts/middleware/broker/src/msg.rs b/contracts/middleware/broker/src/msg.rs index cb412b01..c1a4eff8 100644 --- a/contracts/middleware/broker/src/msg.rs +++ b/contracts/middleware/broker/src/msg.rs @@ -1,37 +1,19 @@ -use std::collections::BTreeMap; - -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Binary}; -use neutron_sdk::bindings::types::InterchainQueryResult; -use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, ValenceType}; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::Addr; +use valence_middleware_utils::type_registry::types::RegistryQueryMsg; #[cw_serde] pub struct InstantiateMsg {} #[cw_serde] pub enum ExecuteMsg { - SetLatestRegistry { version: String, address: String }, + SetRegistry { version: String, address: String }, } #[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(NativeTypeWrapper)] - DecodeProto { - registry_version: Option, - query_id: String, - icq_result: InterchainQueryResult, - }, - #[returns(neutron_sdk::bindings::types::KVKey)] - GetKVKey { - registry_version: Option, - query_id: String, - params: BTreeMap, - }, - #[returns(ValenceType)] - ToCanonical {}, - #[returns(Binary)] - FromCanonical {}, +pub struct QueryMsg { + pub registry_version: Option, + pub query: RegistryQueryMsg, } #[cw_serde] diff --git a/contracts/middleware/broker/src/testing/mod.rs b/contracts/middleware/broker/src/testing/mod.rs index 0241ca07..d568fb4c 100644 --- a/contracts/middleware/broker/src/testing/mod.rs +++ b/contracts/middleware/broker/src/testing/mod.rs @@ -5,7 +5,7 @@ use std::collections::BTreeMap; use cosmwasm_std::{Addr, Binary, StdResult}; use cw_multi_test::{App, AppResponse, ContractWrapper, Executor}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; -use valence_middleware_utils::type_registry::types::NativeTypeWrapper; +use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -73,7 +73,7 @@ impl Default for Suite { impl Suite { fn add_new_registry(&mut self, version: &str, addr: String) -> AppResponse { - let msg = ExecuteMsg::SetLatestRegistry { + let msg = ExecuteMsg::SetRegistry { version: version.to_string(), address: addr, }; @@ -88,22 +88,25 @@ impl Suite { query_id: &str, icq_result: InterchainQueryResult, ) -> StdResult { - let msg = QueryMsg::DecodeProto { + let msg = QueryMsg { registry_version: None, - query_id: query_id.to_string(), - icq_result, + query: RegistryQueryMsg::ReconstructProto { + query_id: query_id.to_string(), + icq_result, + }, }; - self.app .wrap() .query_wasm_smart(self.broker_addr.clone(), &msg) } fn get_kv_key(&mut self, query_id: &str, params: BTreeMap) -> StdResult { - let msg = QueryMsg::GetKVKey { + let msg = QueryMsg { registry_version: None, - query_id: query_id.to_string(), - params, + query: RegistryQueryMsg::KVKey { + type_id: query_id.to_string(), + params, + }, }; self.app diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs index 71d319dd..4cad30ae 100644 --- a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs @@ -44,8 +44,8 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { match msg { - RegistryQueryMsg::Serialize { obj } => try_serialize_obj(obj), - RegistryQueryMsg::Deserialize { type_url, binary } => { + RegistryQueryMsg::FromCanonical { obj } => try_serialize_obj(obj), + RegistryQueryMsg::ToCanonical { type_url, binary } => { let deser = try_deserialize_type_url(type_url, binary)?; to_json_binary(&deser) } diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index 757a3a66..bbed33b4 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -22,10 +22,10 @@ pub enum ValenceType { pub enum RegistryQueryMsg { /// serialize a message to binary #[returns(Binary)] - Serialize { obj: ValenceType }, + FromCanonical { obj: ValenceType }, /// deserialize a message from binary/bytes #[returns(Binary)] - Deserialize { type_url: String, binary: Binary }, + ToCanonical { type_url: String, binary: Binary }, /// get the kvkey used for registering an interchain query #[returns(neutron_sdk::bindings::types::KVKey)] From 22616e18a7748644948e5352a8602530f716edea Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 18 Dec 2024 13:30:56 +0100 Subject: [PATCH 82/92] rename middleware domains to type_registries --- Cargo.toml | 4 ++-- contracts/middleware/type-registries/README.md | 1 + .../osmosis/osmo-26-0-0/.cargo/config.toml | 0 .../osmosis/osmo-26-0-0/Cargo.toml | 0 .../osmosis/osmo-26-0-0/README.md | 0 .../osmosis/osmo-26-0-0/src/contract.rs | 0 .../src/definitions/bank_balance/domain_adapter.rs | 0 .../osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs | 0 .../src/definitions/bank_balance/valence_adapter.rs | 0 .../osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs | 0 .../osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs | 0 .../osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs | 0 .../osmosis/osmo-26-0-0/src/definitions/mod.rs | 0 .../osmosis/osmo-26-0-0/src/lib.rs | 0 14 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 contracts/middleware/type-registries/README.md rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/.cargo/config.toml (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/Cargo.toml (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/README.md (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/contract.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/definitions/mod.rs (100%) rename contracts/middleware/{domains => type-registries}/osmosis/osmo-26-0-0/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 18990f34..df604a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ members = [ "contracts/processor", "contracts/testing/*", "contracts/program-registry", - "contracts/middleware/domains/osmosis/osmo-26-0-0", + "contracts/middleware/type-registries/osmosis/osmo-26-0-0", "contracts/middleware/broker", "packages/*", "program-manager", @@ -77,7 +77,7 @@ valence-osmosis-cl-withdrawer = { path = "contracts/libraries/osmosis-cl- valence-icq-querier = { path = "contracts/libraries/icq-querier", features = ["library"] } # middleware -valence-middleware-osmosis = { path = "contracts/middleware/domains/osmosis/osmo-26-0-0", features = ["library"] } +valence-middleware-osmosis = { path = "contracts/middleware/type-registries/osmosis/osmo-26-0-0", features = ["library"] } valence-middleware-broker = { path = "contracts/middleware/brokers", features = ["library"] } # our packages diff --git a/contracts/middleware/type-registries/README.md b/contracts/middleware/type-registries/README.md new file mode 100644 index 00000000..77c221e2 --- /dev/null +++ b/contracts/middleware/type-registries/README.md @@ -0,0 +1 @@ +# Middleware Type Registries diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/.cargo/config.toml similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/.cargo/config.toml rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/.cargo/config.toml diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/Cargo.toml rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/README.md b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/README.md rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/contract.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/valence_adapter.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/definitions/mod.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs diff --git a/contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/lib.rs similarity index 100% rename from contracts/middleware/domains/osmosis/osmo-26-0-0/src/lib.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/lib.rs From d6ecb31d121a87d444d0ecbeeaedb5dc84518f66 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 18 Dec 2024 14:19:18 +0100 Subject: [PATCH 83/92] middleware & type registry readmes --- contracts/middleware/README.md | 8 ++++++ .../middleware/type-registries/README.md | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 contracts/middleware/README.md diff --git a/contracts/middleware/README.md b/contracts/middleware/README.md new file mode 100644 index 00000000..131b440b --- /dev/null +++ b/contracts/middleware/README.md @@ -0,0 +1,8 @@ +# Valence Middleware + +The Valence Middleware is a set of components that provide +a unified interface for the Valence Type system. + +There are two core elements to the middleware: +- brokers +- type registries diff --git a/contracts/middleware/type-registries/README.md b/contracts/middleware/type-registries/README.md index 77c221e2..452efa78 100644 --- a/contracts/middleware/type-registries/README.md +++ b/contracts/middleware/type-registries/README.md @@ -1 +1,28 @@ # Middleware Type Registries + +*Middleware type registries* are static components that define how +types external to the Valence Protocol are adapted to be used within +Valence programs. + +While type registries can be used independently, they are typically +meant to be registered into a *broker* which will orchestrate different +type registries. With that in mind, it is important to ensure that +every type registry adheres to the standards expected by the broker. + +## Type Registry lifecycle + +Type Registries are static contracts that define their types during +compile time. + +Once a registry is deployed, it is expected to remain unchanged. +If a type change is needed, a new registry should be compiled, deployed, +and registered into the broker to offer the missing or updated +functionality. + +## API + +All type registry instances must implement the same interface defined +in `middleware-utils`. + +With that, the only thing that changes between registries is the +contents of `/definitions` directory. From 3ce96a3dd9fa4d7dec783bfdc15962426306f2b3 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 18 Dec 2024 17:56:14 +0100 Subject: [PATCH 84/92] integrate to & from canonical type conversions to broker --- Cargo.lock | 2 + contracts/middleware/broker/Cargo.toml | 2 + contracts/middleware/broker/src/contract.rs | 36 ++++++-- .../middleware/broker/src/testing/mod.rs | 29 ++++++- .../middleware/broker/src/testing/tests.rs | 87 ++++++++++++++++++- .../middleware/type-registries/README.md | 10 +++ .../osmosis/osmo-26-0-0/src/contract.rs | 64 +++++++++++--- .../src/type_registry/types.rs | 2 +- 8 files changed, 208 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f43cd980..7c6b98ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5318,6 +5318,8 @@ dependencies = [ "cw-ownable", "cw-storage-plus 2.0.0", "neutron-sdk", + "osmosis-std", + "osmosis-std-derive", "prost 0.13.3", "prost-types 0.13.3", "semver", diff --git a/contracts/middleware/broker/Cargo.toml b/contracts/middleware/broker/Cargo.toml index 70887b8e..05a95ee4 100644 --- a/contracts/middleware/broker/Cargo.toml +++ b/contracts/middleware/broker/Cargo.toml @@ -30,3 +30,5 @@ semver = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } valence-middleware-osmosis = { workspace = true } +osmosis-std = "0.26.0" +osmosis-std-derive = "0.26.0" diff --git a/contracts/middleware/broker/src/contract.rs b/contracts/middleware/broker/src/contract.rs index df78fa63..d0e14655 100644 --- a/contracts/middleware/broker/src/contract.rs +++ b/contracts/middleware/broker/src/contract.rs @@ -6,7 +6,7 @@ use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Resp use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use semver::Version; use valence_middleware_utils::{ - type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}, + type_registry::types::{NativeTypeWrapper, RegistryQueryMsg, ValenceType}, MiddlewareError, }; @@ -88,8 +88,15 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { RegistryQueryMsg::KVKey { type_id, params } => { try_get_kv_key(deps, registry.registry_address.to_string(), type_id, params) } - RegistryQueryMsg::ToCanonical { type_url, binary } => try_to_canonical(), - RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(), + RegistryQueryMsg::ToCanonical { type_url, binary } => try_to_canonical( + deps, + registry.registry_address.to_string(), + type_url, + binary, + ), + RegistryQueryMsg::FromCanonical { obj } => { + try_from_canonical(deps, registry.registry_address.to_string(), obj) + } } } @@ -125,10 +132,25 @@ fn try_get_kv_key( to_json_binary(&response) } -fn try_to_canonical() -> StdResult { - Ok(Binary::new("a".as_bytes().to_vec())) +fn try_to_canonical( + deps: Deps, + registry: String, + type_url: String, + binary: Binary, +) -> StdResult { + let response: ValenceType = deps.querier.query_wasm_smart( + registry, + &RegistryQueryMsg::ToCanonical { type_url, binary }, + )?; + to_json_binary(&response) } -fn try_from_canonical() -> StdResult { - Ok(Binary::new("a".as_bytes().to_vec())) +fn try_from_canonical(deps: Deps, registry: String, canonical: ValenceType) -> StdResult { + println!("[broker] try_from_canonical: {:?}", canonical); + let response: NativeTypeWrapper = deps.querier.query_wasm_smart( + registry, + &RegistryQueryMsg::FromCanonical { obj: canonical }, + )?; + println!("[broker] response: {:?}", response); + to_json_binary(&response) } diff --git a/contracts/middleware/broker/src/testing/mod.rs b/contracts/middleware/broker/src/testing/mod.rs index d568fb4c..1e5ace77 100644 --- a/contracts/middleware/broker/src/testing/mod.rs +++ b/contracts/middleware/broker/src/testing/mod.rs @@ -5,7 +5,9 @@ use std::collections::BTreeMap; use cosmwasm_std::{Addr, Binary, StdResult}; use cw_multi_test::{App, AppResponse, ContractWrapper, Executor}; use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; -use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}; +use valence_middleware_utils::type_registry::types::{ + NativeTypeWrapper, RegistryQueryMsg, ValenceType, +}; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -113,4 +115,29 @@ impl Suite { .wrap() .query_wasm_smart(self.broker_addr.clone(), &msg) } + + fn try_to_canonical(&mut self, type_url: &str, binary: Binary) -> StdResult { + let msg = QueryMsg { + registry_version: None, + query: RegistryQueryMsg::ToCanonical { + type_url: type_url.to_string(), + binary, + }, + }; + + self.app + .wrap() + .query_wasm_smart(self.broker_addr.clone(), &msg) + } + + fn try_from_canonical(&mut self, obj: ValenceType) -> StdResult { + let msg = QueryMsg { + registry_version: None, + query: RegistryQueryMsg::FromCanonical { obj }, + }; + + self.app + .wrap() + .query_wasm_smart(self.broker_addr.clone(), &msg) + } } diff --git a/contracts/middleware/broker/src/testing/tests.rs b/contracts/middleware/broker/src/testing/tests.rs index ae0a1b57..a6c63e1a 100644 --- a/contracts/middleware/broker/src/testing/tests.rs +++ b/contracts/middleware/broker/src/testing/tests.rs @@ -1,12 +1,16 @@ use std::collections::BTreeMap; -use cosmwasm_std::{to_json_binary, Binary}; +use cosmwasm_std::{coin, to_json_binary, Binary}; use neutron_sdk::bindings::types::{InterchainQueryResult, StorageValue}; +use osmosis_std::types::osmosis::gamm::v1beta1::Pool; +use valence_middleware_utils::{ + canonical_types::pools::xyk::ValenceXykPool, type_registry::types::ValenceType, +}; use super::Suite; #[test] -fn test_init() { +fn test_get_kv_key() { let mut suite = Suite::default(); let resp = suite.add_new_registry("1.0.0", suite.registry_addr.to_string()); @@ -47,3 +51,82 @@ fn test_reconstruct_proto() { let reconstructed_result = suite.query_decode_proto("gamm_pool", icq_result).unwrap(); println!("reconstructed result: {:?}", reconstructed_result); } + +#[test] +fn test_into_canonical() { + let mut suite = Suite::default(); + + suite.add_new_registry("1.0.0", suite.registry_addr.to_string()); + + let pool = Pool::default(); + println!("pool: {:?}", pool); + + let binary = to_json_binary(&Pool::default()).unwrap(); + + let resp: ValenceType = suite.try_to_canonical("gamm_pool", binary).unwrap(); + + println!("resp: {:?}", resp); +} + +#[test] +fn test_from_canonical() { + let mut suite = Suite::default(); + + suite.add_new_registry("1.0.0", suite.registry_addr.to_string()); + + let canonical = ValenceType::XykPool(ValenceXykPool { + assets: vec![ + coin( + 100000000, + "ibc/4E41ED8F3DCAEA15F4D6ADC6EDD7C04A676160735C9710B904B7BF53525B56D6", + ), + coin(100000000, "uosmo"), + ], + total_shares: "100000000000000000000".to_string(), + domain_specific_fields: BTreeMap::from([ + ("pool_asset_ibc/4E41ED8F3DCAEA15F4D6ADC6EDD7C04A676160735C9710B904B7BF53525B56D6_weight".to_string(), + to_json_binary(&"1073741824").unwrap() + ), + ("pool_asset_uosmo_weight".to_string(), + to_json_binary(&"1073741824").unwrap() + ), + ( + "shares_denom".to_string(), + to_json_binary(&"gamm/pool/1").unwrap(), + ), + ( + "address".to_string(), + to_json_binary(&"osmo19e2mf7cywkv7zaug6nk5f87d07fxrdgrladvymh2gwv5crvm3vnsuewhh7") + .unwrap(), + ), + ("id".to_string(), to_json_binary(&1).unwrap()), + ( + "future_pool_governor".to_string(), + to_json_binary(&"128h").unwrap(), + ), + ( + "total_weight".to_string(), + to_json_binary(&"2147483648").unwrap(), + ), + ( + "pool_params".to_string(), + to_json_binary(&Pool::default().pool_params).unwrap(), + ), + ]), + }); + + let native_binary_response = suite.try_from_canonical(canonical).unwrap(); + + let revert_canonical: ValenceType = suite + .try_to_canonical("gamm_pool", native_binary_response.binary) + .unwrap(); + + match revert_canonical { + ValenceType::XykPool(valence_xyk_pool) => { + assert_eq!(valence_xyk_pool.assets.len(), 2); + assert_eq!(valence_xyk_pool.total_shares, "100000000000000000000"); + assert_eq!(valence_xyk_pool.domain_specific_fields.len(), 8); + } + _ => panic!(), + } +} diff --git a/contracts/middleware/type-registries/README.md b/contracts/middleware/type-registries/README.md index 452efa78..a05e16bb 100644 --- a/contracts/middleware/type-registries/README.md +++ b/contracts/middleware/type-registries/README.md @@ -26,3 +26,13 @@ in `middleware-utils`. With that, the only thing that changes between registries is the contents of `/definitions` directory. + +## Module organization + +Under `/type-registries`, organisation is outlined in a domain-driven +manner. Types are grouped by their domain and are expected to be +self-contained. + +For instance, `/type-registries/osmosis` is expected to contain all +registry instances related to the Osmosis domain. Different instances +should be versioned by semver which follows the external domain versioning. diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs index 4cad30ae..abb9063e 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs @@ -3,11 +3,15 @@ use std::collections::BTreeMap; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, + from_json, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, + StdResult, }; use neutron_sdk::bindings::types::InterchainQueryResult; +use osmosis_std::types::{ + cosmos::bank::v1beta1::QueryBalanceResponse, osmosis::gamm::v1beta1::Pool, +}; use valence_middleware_utils::{ - canonical_types::pools::xyk::ValenceXykPool, + canonical_types::ValenceTypeAdapter, type_registry::types::{ NativeTypeWrapper, RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, ValenceType, @@ -44,10 +48,10 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { match msg { - RegistryQueryMsg::FromCanonical { obj } => try_serialize_obj(obj), + RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(obj), RegistryQueryMsg::ToCanonical { type_url, binary } => { - let deser = try_deserialize_type_url(type_url, binary)?; - to_json_binary(&deser) + let canonical = try_to_canonical(type_url, binary)?; + to_json_binary(&canonical) } RegistryQueryMsg::KVKey { type_id, params } => try_get_kv_key(type_id, params), RegistryQueryMsg::ReconstructProto { @@ -87,14 +91,48 @@ fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> } } -fn try_serialize_obj(_object: ValenceType) -> StdResult { - Ok(Binary::new("a".as_bytes().to_vec())) +fn try_from_canonical(object: ValenceType) -> StdResult { + println!("[registry] converting valence type to binary: {:?}", object); + match &object { + ValenceType::XykPool(_) => { + let obj = OsmosisXykPool::try_from_canonical(object) + .map_err(|e| StdError::generic_err(e.to_string()))?; + to_json_binary(&NativeTypeWrapper { + binary: to_json_binary(&obj)?, + }) + } + ValenceType::BankBalance(_) => { + let obj = OsmosisBankBalance::try_from_canonical(object) + .map_err(|e| StdError::generic_err(e.to_string()))?; + to_json_binary(&NativeTypeWrapper { + binary: to_json_binary(&obj)?, + }) + } + } } -fn try_deserialize_type_url(_type_url: String, _binary: Binary) -> StdResult { - Ok(ValenceType::XykPool(ValenceXykPool { - assets: vec![], - total_shares: "hi".to_string(), - domain_specific_fields: BTreeMap::new(), - })) +fn try_to_canonical(type_url: String, binary: Binary) -> StdResult { + println!("[registry] converting {type_url} binary to canonical valence type"); + let canonical_type = match type_url.as_str() { + "gamm_pool" => { + let obj: Pool = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; + + let native_type = OsmosisXykPool(obj); + native_type + .try_to_canonical() + .map_err(|e| StdError::generic_err(e.to_string()))? + } + "bank_balances" => { + let obj: QueryBalanceResponse = + from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; + + let native_type = OsmosisBankBalance(obj); + native_type + .try_to_canonical() + .map_err(|e| StdError::generic_err(e.to_string()))? + } + _ => return Err(StdError::generic_err("unknown type_id")), + }; + + Ok(canonical_type) } diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index bbed33b4..64c5531f 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -21,7 +21,7 @@ pub enum ValenceType { #[derive(QueryResponses)] pub enum RegistryQueryMsg { /// serialize a message to binary - #[returns(Binary)] + #[returns(NativeTypeWrapper)] FromCanonical { obj: ValenceType }, /// deserialize a message from binary/bytes #[returns(Binary)] From d46e8a38348f79f83f556123abe26ce671e60b4a Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 18 Dec 2024 18:31:42 +0100 Subject: [PATCH 85/92] remove hardcoded type urls; add middleware-utils readme --- .../middleware/broker/src/testing/tests.rs | 6 ++++-- .../osmosis/osmo-26-0-0/README.md | 1 - .../osmosis/osmo-26-0-0/src/contract.rs | 14 ++++++++------ packages/middleware-utils/README.md | 19 +++++++++++++++++++ packages/middleware-utils/src/lib.rs | 5 ++--- .../src/type_registry/types.rs | 4 ++-- 6 files changed, 35 insertions(+), 14 deletions(-) delete mode 100644 contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md create mode 100644 packages/middleware-utils/README.md diff --git a/contracts/middleware/broker/src/testing/tests.rs b/contracts/middleware/broker/src/testing/tests.rs index a6c63e1a..b0bbd2f3 100644 --- a/contracts/middleware/broker/src/testing/tests.rs +++ b/contracts/middleware/broker/src/testing/tests.rs @@ -19,7 +19,7 @@ fn test_get_kv_key() { let params = BTreeMap::from([("pool_id".to_string(), to_json_binary(&1u64).unwrap())]); - let kv_key = suite.get_kv_key("gamm_pool", params).unwrap(); + let kv_key = suite.get_kv_key(Pool::TYPE_URL, params).unwrap(); println!("kv_key: {:?}", kv_key); } @@ -48,7 +48,9 @@ fn test_reconstruct_proto() { revision: 1, }; - let reconstructed_result = suite.query_decode_proto("gamm_pool", icq_result).unwrap(); + let reconstructed_result = suite + .query_decode_proto(Pool::TYPE_URL, icq_result) + .unwrap(); println!("reconstructed result: {:?}", reconstructed_result); } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md deleted file mode 100644 index e2b0ee8f..00000000 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/README.md +++ /dev/null @@ -1 +0,0 @@ -# Osmosis middleware diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs index abb9063e..a9c9c2f9 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs @@ -63,8 +63,8 @@ pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResult { let kv_key = match type_id.as_str() { - "gamm_pool" => OsmosisXykPool::get_kv_key(params), - "bank_balances" => OsmosisBankBalance::get_kv_key(params), + Pool::TYPE_URL => OsmosisXykPool::get_kv_key(params), + QueryBalanceResponse::TYPE_URL => OsmosisBankBalance::get_kv_key(params), _ => return Err(StdError::generic_err("unknown type_id")), }; @@ -78,8 +78,10 @@ fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResul fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> StdResult { let reconstruction_result = match type_id.as_str() { - "gamm_pool" => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), - "bank_balances" => OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result), + Pool::TYPE_URL => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), + QueryBalanceResponse::TYPE_URL => { + OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result) + } _ => return Err(StdError::generic_err("unknown type_id")), }; @@ -114,7 +116,7 @@ fn try_from_canonical(object: ValenceType) -> StdResult { fn try_to_canonical(type_url: String, binary: Binary) -> StdResult { println!("[registry] converting {type_url} binary to canonical valence type"); let canonical_type = match type_url.as_str() { - "gamm_pool" => { + Pool::TYPE_URL => { let obj: Pool = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; let native_type = OsmosisXykPool(obj); @@ -122,7 +124,7 @@ fn try_to_canonical(type_url: String, binary: Binary) -> StdResult .try_to_canonical() .map_err(|e| StdError::generic_err(e.to_string()))? } - "bank_balances" => { + QueryBalanceResponse::TYPE_URL => { let obj: QueryBalanceResponse = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; diff --git a/packages/middleware-utils/README.md b/packages/middleware-utils/README.md new file mode 100644 index 00000000..80cdfe6e --- /dev/null +++ b/packages/middleware-utils/README.md @@ -0,0 +1,19 @@ +# Middleware utils + +Middleware utils package defines the unified types and interfaces that +are used meant to be used by middleware contracts. + +There are two main types of such definitions: +- canonical types +- middleware API + +## Canonical Types + +Types declared in `./src/canonical_types` package are ones ready to be +used by Valence Programs. + +## Type Registry + +Type registry declarations define the common API used by the middleware. +All instances of type registries are expected to use those declarations +in order to be compatible with Valence Protocol. diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index 033b341c..bd36dd61 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -39,7 +39,7 @@ pub enum MiddlewareError { pub fn try_unpack_domain_specific_value( key: &str, - domain_specific_fields: &BTreeMap, + domain_specific_fields: &BTreeMap, ) -> StdResult where T: DeserializeOwned, @@ -47,8 +47,7 @@ where let binary = domain_specific_fields .get(key) .ok_or(StdError::generic_err(format!( - "failed to get {} field from domain specific fields", - key + "failed to get {key} field from domain specific fields" ))) .unwrap(); diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index 64c5531f..a92dac12 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Binary; -use neutron_sdk::bindings::types::InterchainQueryResult; +use neutron_sdk::bindings::types::{InterchainQueryResult, KVKey}; use crate::canonical_types::{bank::balance::ValenceBankBalance, pools::xyk::ValenceXykPool}; @@ -28,7 +28,7 @@ pub enum RegistryQueryMsg { ToCanonical { type_url: String, binary: Binary }, /// get the kvkey used for registering an interchain query - #[returns(neutron_sdk::bindings::types::KVKey)] + #[returns(KVKey)] KVKey { type_id: String, params: BTreeMap, From 8423e2fcfb9995838de6e1a2192645f5dc4e95d5 Mon Sep 17 00:00:00 2001 From: bekauz Date: Wed, 18 Dec 2024 19:34:02 +0100 Subject: [PATCH 86/92] wip: type registry unifying api macro seems to be working but i have trust issues --- .../middleware/broker/src/testing/tests.rs | 4 +- .../osmosis/osmo-26-0-0/src/contract.rs | 188 +++++++++--------- .../src/definitions/bank_balance/mod.rs | 6 + .../src/definitions/gamm_pool/mod.rs | 8 +- .../osmo-26-0-0/src/definitions/mod.rs | 33 +++ .../src/type_registry/macros.rs | 73 +++++++ .../middleware-utils/src/type_registry/mod.rs | 1 + 7 files changed, 220 insertions(+), 93 deletions(-) create mode 100644 packages/middleware-utils/src/type_registry/macros.rs diff --git a/contracts/middleware/broker/src/testing/tests.rs b/contracts/middleware/broker/src/testing/tests.rs index b0bbd2f3..1ad223ad 100644 --- a/contracts/middleware/broker/src/testing/tests.rs +++ b/contracts/middleware/broker/src/testing/tests.rs @@ -65,7 +65,7 @@ fn test_into_canonical() { let binary = to_json_binary(&Pool::default()).unwrap(); - let resp: ValenceType = suite.try_to_canonical("gamm_pool", binary).unwrap(); + let resp: ValenceType = suite.try_to_canonical(Pool::TYPE_URL, binary).unwrap(); println!("resp: {:?}", resp); } @@ -120,7 +120,7 @@ fn test_from_canonical() { let native_binary_response = suite.try_from_canonical(canonical).unwrap(); let revert_canonical: ValenceType = suite - .try_to_canonical("gamm_pool", native_binary_response.binary) + .try_to_canonical(Pool::TYPE_URL, native_binary_response.binary) .unwrap(); match revert_canonical { diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs index a9c9c2f9..ba3609db 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs @@ -19,7 +19,9 @@ use valence_middleware_utils::{ IcqIntegration, }; -use crate::definitions::{bank_balance::OsmosisBankBalance, gamm_pool::OsmosisXykPool}; +use crate::definitions::{ + bank_balance::OsmosisBankBalance, gamm_pool::OsmosisXykPool, handle_query, +}; // version info for migration info const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); @@ -47,94 +49,100 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { - match msg { - RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(obj), - RegistryQueryMsg::ToCanonical { type_url, binary } => { - let canonical = try_to_canonical(type_url, binary)?; - to_json_binary(&canonical) - } - RegistryQueryMsg::KVKey { type_id, params } => try_get_kv_key(type_id, params), - RegistryQueryMsg::ReconstructProto { - query_id, - icq_result, - } => try_reconstruct_proto(query_id, icq_result), - } -} - -fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResult { - let kv_key = match type_id.as_str() { - Pool::TYPE_URL => OsmosisXykPool::get_kv_key(params), - QueryBalanceResponse::TYPE_URL => OsmosisBankBalance::get_kv_key(params), - _ => return Err(StdError::generic_err("unknown type_id")), - }; - - println!("[registry] kv key: {:?}", kv_key); - - match kv_key { - Ok(kv) => to_json_binary(&kv), - Err(_) => Err(StdError::generic_err("failed to read kv key")), - } + println!("[registry] delegating query to macro handler & hoping for the best"); + handle_query(msg) } -fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> StdResult { - let reconstruction_result = match type_id.as_str() { - Pool::TYPE_URL => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), - QueryBalanceResponse::TYPE_URL => { - OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result) - } - _ => return Err(StdError::generic_err("unknown type_id")), - }; - - match reconstruction_result { - Ok(res) => to_json_binary(&NativeTypeWrapper { binary: res }), - Err(_) => Err(StdError::generic_err( - "failed to reconstruct type from proto", - )), - } -} - -fn try_from_canonical(object: ValenceType) -> StdResult { - println!("[registry] converting valence type to binary: {:?}", object); - match &object { - ValenceType::XykPool(_) => { - let obj = OsmosisXykPool::try_from_canonical(object) - .map_err(|e| StdError::generic_err(e.to_string()))?; - to_json_binary(&NativeTypeWrapper { - binary: to_json_binary(&obj)?, - }) - } - ValenceType::BankBalance(_) => { - let obj = OsmosisBankBalance::try_from_canonical(object) - .map_err(|e| StdError::generic_err(e.to_string()))?; - to_json_binary(&NativeTypeWrapper { - binary: to_json_binary(&obj)?, - }) - } - } -} - -fn try_to_canonical(type_url: String, binary: Binary) -> StdResult { - println!("[registry] converting {type_url} binary to canonical valence type"); - let canonical_type = match type_url.as_str() { - Pool::TYPE_URL => { - let obj: Pool = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; - - let native_type = OsmosisXykPool(obj); - native_type - .try_to_canonical() - .map_err(|e| StdError::generic_err(e.to_string()))? - } - QueryBalanceResponse::TYPE_URL => { - let obj: QueryBalanceResponse = - from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; - - let native_type = OsmosisBankBalance(obj); - native_type - .try_to_canonical() - .map_err(|e| StdError::generic_err(e.to_string()))? - } - _ => return Err(StdError::generic_err("unknown type_id")), - }; - - Ok(canonical_type) -} +// #[cfg_attr(not(feature = "library"), entry_point)] +// pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { +// match msg { +// RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(obj), +// RegistryQueryMsg::ToCanonical { type_url, binary } => { +// let canonical = try_to_canonical(type_url, binary)?; +// to_json_binary(&canonical) +// } +// RegistryQueryMsg::KVKey { type_id, params } => try_get_kv_key(type_id, params), +// RegistryQueryMsg::ReconstructProto { +// query_id, +// icq_result, +// } => try_reconstruct_proto(query_id, icq_result), +// } +// } + +// fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResult { +// let kv_key = match type_id.as_str() { +// Pool::TYPE_URL => OsmosisXykPool::get_kv_key(params), +// QueryBalanceResponse::TYPE_URL => OsmosisBankBalance::get_kv_key(params), +// _ => return Err(StdError::generic_err("unknown type_id")), +// }; + +// println!("[registry] kv key: {:?}", kv_key); + +// match kv_key { +// Ok(kv) => to_json_binary(&kv), +// Err(_) => Err(StdError::generic_err("failed to read kv key")), +// } +// } + +// fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> StdResult { +// let reconstruction_result = match type_id.as_str() { +// Pool::TYPE_URL => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), +// QueryBalanceResponse::TYPE_URL => { +// OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result) +// } +// _ => return Err(StdError::generic_err("unknown type_id")), +// }; + +// match reconstruction_result { +// Ok(res) => to_json_binary(&NativeTypeWrapper { binary: res }), +// Err(_) => Err(StdError::generic_err( +// "failed to reconstruct type from proto", +// )), +// } +// } + +// fn try_from_canonical(object: ValenceType) -> StdResult { +// println!("[registry] converting valence type to binary: {:?}", object); +// match &object { +// ValenceType::XykPool(_) => { +// let obj = OsmosisXykPool::try_from_canonical(object) +// .map_err(|e| StdError::generic_err(e.to_string()))?; +// to_json_binary(&NativeTypeWrapper { +// binary: to_json_binary(&obj)?, +// }) +// } +// ValenceType::BankBalance(_) => { +// let obj = OsmosisBankBalance::try_from_canonical(object) +// .map_err(|e| StdError::generic_err(e.to_string()))?; +// to_json_binary(&NativeTypeWrapper { +// binary: to_json_binary(&obj)?, +// }) +// } +// } +// } + +// fn try_to_canonical(type_url: String, binary: Binary) -> StdResult { +// println!("[registry] converting {type_url} binary to canonical valence type"); +// let canonical_type = match type_url.as_str() { +// Pool::TYPE_URL => { +// let obj: Pool = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; + +// let native_type = OsmosisXykPool(obj); +// native_type +// .try_to_canonical() +// .map_err(|e| StdError::generic_err(e.to_string()))? +// } +// QueryBalanceResponse::TYPE_URL => { +// let obj: QueryBalanceResponse = +// from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; + +// let native_type = OsmosisBankBalance(obj); +// native_type +// .try_to_canonical() +// .map_err(|e| StdError::generic_err(e.to_string()))? +// } +// _ => return Err(StdError::generic_err("unknown type_id")), +// }; + +// Ok(canonical_type) +// } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs index fd97e624..626adf91 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs @@ -7,3 +7,9 @@ const ADDR_KEY: &str = "addr"; const DENOM_KEY: &str = "denom"; pub struct OsmosisBankBalance(pub QueryBalanceResponse); + +impl From for OsmosisBankBalance { + fn from(balance: QueryBalanceResponse) -> Self { + Self(balance) + } +} diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs index 14d305dc..bc26e92c 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs @@ -13,6 +13,12 @@ const STORAGE_PREFIX: &str = "gamm"; pub struct OsmosisXykPool(pub Pool); +impl From for OsmosisXykPool { + fn from(pool: Pool) -> Self { + Self(pool) + } +} + #[cfg(test)] mod tests { use cosmwasm_std::{from_json, Binary}; @@ -71,6 +77,6 @@ mod tests { // convert the valence type back into the external type let osmo_pool = OsmosisXykPool::try_from_canonical(canonical_valence_pool).unwrap(); - assert_eq!(osmo_pool.pool_assets.len(), 3); + assert_eq!(osmo_pool.pool_assets.len(), 2); } } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs index 02796673..b600e369 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -1,6 +1,39 @@ +use bank_balance::OsmosisBankBalance; +use gamm_pool::OsmosisXykPool; +use osmosis_std::types::{ + cosmos::bank::v1beta1::QueryBalanceResponse, osmosis::gamm::v1beta1::Pool, +}; +use valence_middleware_utils::register_types; + pub mod bank_balance; pub mod gamm_pool; // TODO: embed the previously deployed version identifier there // to ensure that types declared here implement a 1-1 mapper from // the outdated version to this one. + +// thought: these definitions could also be treated as optional fields. +// e.g. not every type needs to be ICQ-able, so some types could miss +// the ICQ adapter implementation. If registry receives an ICQ request +// regarding a type that does not have an ICQ adapter, we return a clear +// error saying that the type is not ICQ-able (and perhaps provide the +// functionality that is available). +// such optionality could also enable us to make use of the semver more +// extensively. for instance, the major/minor/patch versions could follow +// the upstream type, and various additions could be attached to the semver +// as pre-release identifiers. + +register_types! { + "/osmosis.gamm.v1beta1.Pool" => { + native_type: Pool, + adapter: OsmosisXykPool, + to_valence: ValenceType::XykPool, + // migrate_from: osmo_25_0_0::Pool, + }, + "/cosmos.bank.v1beta1.QueryBalanceResponse" => { + native_type: QueryBalanceResponse, + adapter: OsmosisBankBalance, + to_valence: ValenceType::BankBalance, + // migrate_from: osmo_25_0_0::QueryBalanceResponse, + } +} diff --git a/packages/middleware-utils/src/type_registry/macros.rs b/packages/middleware-utils/src/type_registry/macros.rs new file mode 100644 index 00000000..641468ef --- /dev/null +++ b/packages/middleware-utils/src/type_registry/macros.rs @@ -0,0 +1,73 @@ +#[macro_export] +macro_rules! register_types { + ( + $( + $type_id:expr => { + native_type: $native:ty, + adapter: $adapter:ty, + to_valence: $to_valence:ty, + } + ),* + ) => { + pub fn handle_query(msg: $crate::type_registry::types::RegistryQueryMsg) + -> ::cosmwasm_std::StdResult<::cosmwasm_std::Binary> + { + use ::cosmwasm_std::{StdError, Binary, from_json, to_json_binary}; + use $crate::type_registry::types::{ValenceType, NativeTypeWrapper}; + use $crate::canonical_types::ValenceTypeAdapter; + use $crate::IcqIntegration; + use $crate::type_registry::types::RegistryQueryMsg; + + match msg { + RegistryQueryMsg::ToCanonical { type_url, binary } => { + match type_url.as_str() { + $( + $type_id => { + let native: $native = from_json(&binary)?; + let adapter = <$adapter>::from(native); + let canonical = adapter.try_to_canonical() + .map_err(|_| StdError::generic_err("failed to convert to canonical"))?; + to_json_binary(&canonical) + }, + )* + _ => Err(StdError::generic_err("unknown type")) + } + }, + RegistryQueryMsg::FromCanonical { obj } => { + $( + if let Ok(native) = <$adapter>::try_from_canonical(obj.clone()) { + return to_json_binary(&NativeTypeWrapper { + binary: to_json_binary(&native)? + }); + } + )* + Err(StdError::generic_err("no matching type found for conversion")) + }, + RegistryQueryMsg::KVKey { type_id, params } => { + match type_id.as_str() { + $( + $type_id => { + let kv_key = <$adapter>::get_kv_key(params) + .map_err(|_| StdError::generic_err("failed to get kvkey"))?; + to_json_binary(&kv_key) + }, + )* + _ => Err(::cosmwasm_std::StdError::generic_err("unknown type")) + } + }, + RegistryQueryMsg::ReconstructProto { query_id, icq_result } => { + match query_id.as_str() { + $( + $type_id => { + let binary = <$adapter>::decode_and_reconstruct(query_id, icq_result) + .map_err(|_| StdError::generic_err("failed to reconstruct type from proto"))?; + to_json_binary(&NativeTypeWrapper { binary }) + }, + )* + _ => Err(::cosmwasm_std::StdError::generic_err("unknown type")) + } + } + } + } + } +} diff --git a/packages/middleware-utils/src/type_registry/mod.rs b/packages/middleware-utils/src/type_registry/mod.rs index cd408564..9bedb0e5 100644 --- a/packages/middleware-utils/src/type_registry/mod.rs +++ b/packages/middleware-utils/src/type_registry/mod.rs @@ -1 +1,2 @@ +pub mod macros; pub mod types; From 594bb4d31dd1fbd4bc8a667d518dfed0943907f3 Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 19 Dec 2024 14:50:30 +0100 Subject: [PATCH 87/92] cleanup --- Cargo.lock | 1 + contracts/middleware/broker/src/state.rs | 1 + .../osmosis/osmo-26-0-0/Cargo.toml | 1 + .../osmosis/osmo-26-0-0/src/contract.rs | 129 ++---------------- .../{domain_adapter.rs => icq_adapter.rs} | 0 .../src/definitions/bank_balance/mod.rs | 2 +- .../{domain_adapter.rs => icq_adapter.rs} | 6 +- .../src/definitions/gamm_pool/mod.rs | 2 +- .../definitions/gamm_pool/valence_adapter.rs | 67 +++------ .../osmo-26-0-0/src/definitions/mod.rs | 10 +- .../src/canonical_types/pools/xyk.rs | 11 +- packages/middleware-utils/src/lib.rs | 3 + .../src/type_registry/types.rs | 3 + 13 files changed, 58 insertions(+), 178 deletions(-) rename contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/{domain_adapter.rs => icq_adapter.rs} (100%) rename contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/{domain_adapter.rs => icq_adapter.rs} (97%) diff --git a/Cargo.lock b/Cargo.lock index 7c6b98ad..8e194347 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5338,6 +5338,7 @@ dependencies = [ "cosmwasm-std 2.1.4", "cw-ownable", "cw-storage-plus 2.0.0", + "cw2 2.0.0", "neutron-sdk", "osmosis-std", "osmosis-std-derive", diff --git a/contracts/middleware/broker/src/state.rs b/contracts/middleware/broker/src/state.rs index 9ba8d260..0656f83b 100644 --- a/contracts/middleware/broker/src/state.rs +++ b/contracts/middleware/broker/src/state.rs @@ -2,5 +2,6 @@ use cw_storage_plus::{Item, Map}; use crate::msg::TypeRegistry; +// semver -> TypeRegistry pub const ACTIVE_REGISTRIES: Map = Map::new("active_registries"); pub const LATEST: Item = Item::new("latest"); diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml index e7f61bf6..0120480d 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/Cargo.toml @@ -27,6 +27,7 @@ thiserror = { workspace = true } serde_json = { workspace = true } cw-storage-plus = { workspace = true } valence-middleware-utils = { workspace = true } +cw2 = { workspace = true } [dev-dependencies] osmosis-test-tube = { workspace = true } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs index ba3609db..c59cd28e 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/contract.rs @@ -1,39 +1,24 @@ -use std::collections::BTreeMap; - +use crate::definitions::handle_query; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{ - from_json, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, - StdResult, -}; -use neutron_sdk::bindings::types::InterchainQueryResult; -use osmosis_std::types::{ - cosmos::bank::v1beta1::QueryBalanceResponse, osmosis::gamm::v1beta1::Pool, -}; -use valence_middleware_utils::{ - canonical_types::ValenceTypeAdapter, - type_registry::types::{ - NativeTypeWrapper, RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, - ValenceType, - }, - IcqIntegration, -}; - -use crate::definitions::{ - bank_balance::OsmosisBankBalance, gamm_pool::OsmosisXykPool, handle_query, +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; +use cw2::set_contract_version; +use valence_middleware_utils::type_registry::types::{ + RegistryExecuteMsg, RegistryInstantiateMsg, RegistryQueryMsg, }; // version info for migration info -const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); -const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( - _deps: DepsMut, + deps: DepsMut, _env: Env, _info: MessageInfo, _msg: RegistryInstantiateMsg, ) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; Ok(Response::default()) } @@ -44,7 +29,7 @@ pub fn execute( _info: MessageInfo, _msg: RegistryExecuteMsg, ) -> Result { - Ok(Response::default()) + unimplemented!("execute is disabled") } #[cfg_attr(not(feature = "library"), entry_point)] @@ -52,97 +37,3 @@ pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult println!("[registry] delegating query to macro handler & hoping for the best"); handle_query(msg) } - -// #[cfg_attr(not(feature = "library"), entry_point)] -// pub fn query(_deps: Deps, _env: Env, msg: RegistryQueryMsg) -> StdResult { -// match msg { -// RegistryQueryMsg::FromCanonical { obj } => try_from_canonical(obj), -// RegistryQueryMsg::ToCanonical { type_url, binary } => { -// let canonical = try_to_canonical(type_url, binary)?; -// to_json_binary(&canonical) -// } -// RegistryQueryMsg::KVKey { type_id, params } => try_get_kv_key(type_id, params), -// RegistryQueryMsg::ReconstructProto { -// query_id, -// icq_result, -// } => try_reconstruct_proto(query_id, icq_result), -// } -// } - -// fn try_get_kv_key(type_id: String, params: BTreeMap) -> StdResult { -// let kv_key = match type_id.as_str() { -// Pool::TYPE_URL => OsmosisXykPool::get_kv_key(params), -// QueryBalanceResponse::TYPE_URL => OsmosisBankBalance::get_kv_key(params), -// _ => return Err(StdError::generic_err("unknown type_id")), -// }; - -// println!("[registry] kv key: {:?}", kv_key); - -// match kv_key { -// Ok(kv) => to_json_binary(&kv), -// Err(_) => Err(StdError::generic_err("failed to read kv key")), -// } -// } - -// fn try_reconstruct_proto(type_id: String, icq_result: InterchainQueryResult) -> StdResult { -// let reconstruction_result = match type_id.as_str() { -// Pool::TYPE_URL => OsmosisXykPool::decode_and_reconstruct(type_id, icq_result), -// QueryBalanceResponse::TYPE_URL => { -// OsmosisBankBalance::decode_and_reconstruct(type_id, icq_result) -// } -// _ => return Err(StdError::generic_err("unknown type_id")), -// }; - -// match reconstruction_result { -// Ok(res) => to_json_binary(&NativeTypeWrapper { binary: res }), -// Err(_) => Err(StdError::generic_err( -// "failed to reconstruct type from proto", -// )), -// } -// } - -// fn try_from_canonical(object: ValenceType) -> StdResult { -// println!("[registry] converting valence type to binary: {:?}", object); -// match &object { -// ValenceType::XykPool(_) => { -// let obj = OsmosisXykPool::try_from_canonical(object) -// .map_err(|e| StdError::generic_err(e.to_string()))?; -// to_json_binary(&NativeTypeWrapper { -// binary: to_json_binary(&obj)?, -// }) -// } -// ValenceType::BankBalance(_) => { -// let obj = OsmosisBankBalance::try_from_canonical(object) -// .map_err(|e| StdError::generic_err(e.to_string()))?; -// to_json_binary(&NativeTypeWrapper { -// binary: to_json_binary(&obj)?, -// }) -// } -// } -// } - -// fn try_to_canonical(type_url: String, binary: Binary) -> StdResult { -// println!("[registry] converting {type_url} binary to canonical valence type"); -// let canonical_type = match type_url.as_str() { -// Pool::TYPE_URL => { -// let obj: Pool = from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; - -// let native_type = OsmosisXykPool(obj); -// native_type -// .try_to_canonical() -// .map_err(|e| StdError::generic_err(e.to_string()))? -// } -// QueryBalanceResponse::TYPE_URL => { -// let obj: QueryBalanceResponse = -// from_json(&binary).map_err(|e| StdError::generic_err(e.to_string()))?; - -// let native_type = OsmosisBankBalance(obj); -// native_type -// .try_to_canonical() -// .map_err(|e| StdError::generic_err(e.to_string()))? -// } -// _ => return Err(StdError::generic_err("unknown type_id")), -// }; - -// Ok(canonical_type) -// } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/icq_adapter.rs similarity index 100% rename from contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/domain_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/icq_adapter.rs diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs index 626adf91..0676ba13 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/bank_balance/mod.rs @@ -1,6 +1,6 @@ use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; -pub mod domain_adapter; +pub mod icq_adapter; pub mod valence_adapter; const ADDR_KEY: &str = "addr"; diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/icq_adapter.rs similarity index 97% rename from contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs rename to contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/icq_adapter.rs index 3e2a71b3..21f0fd6c 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/domain_adapter.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/icq_adapter.rs @@ -37,9 +37,9 @@ impl IcqIntegration for OsmosisXykPool { .try_into() .map_err(|_| StdError::generic_err("failed to parse into pool"))?; - let binary = to_json_binary(&osmo_pool)?; - - Ok(binary) + to_json_binary(&osmo_pool) + .map_err(StdError::from) + .map_err(MiddlewareError::Std) } } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs index bc26e92c..f1aaf28f 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/mod.rs @@ -1,6 +1,6 @@ use osmosis_std::types::osmosis::gamm::v1beta1::Pool; -pub mod domain_adapter; +pub mod icq_adapter; pub mod valence_adapter; const ADDRESS_KEY: &str = "address"; diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs index 41b7f01a..bf8d9ef4 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/gamm_pool/valence_adapter.rs @@ -4,13 +4,12 @@ use std::str::FromStr; use cosmwasm_std::coin; use cosmwasm_std::to_json_binary; -use cosmwasm_std::StdError; use osmosis_std::types::osmosis::gamm::v1beta1::{Pool, PoolParams}; use osmosis_std::types::{cosmos::base::v1beta1::Coin, osmosis::gamm::v1beta1::PoolAsset}; use valence_middleware_utils::canonical_types::pools::xyk::ValenceXykPool; use valence_middleware_utils::canonical_types::ValenceTypeAdapter; use valence_middleware_utils::type_registry::types::ValenceType; -use valence_middleware_utils::{try_unpack_domain_specific_value, MiddlewareError}; +use valence_middleware_utils::MiddlewareError; use super::{ OsmosisXykPool, ADDRESS_KEY, FUTURE_POOL_GOVERNOR_KEY, ID_KEY, POOL_PARAMS_KEY, @@ -75,62 +74,33 @@ impl ValenceTypeAdapter for OsmosisXykPool { } fn try_from_canonical(canonical: ValenceType) -> Result { - let canonical_inner = match canonical { + let inner = match canonical { ValenceType::XykPool(pool) => pool, _ => { - return Err(MiddlewareError::Std(StdError::generic_err( - "canonical inner type mismatch", - ))) + return Err(MiddlewareError::CanonicalConversionError( + "canonical inner type mismatch".to_string(), + )) } }; - // unpack the pool address - let address: String = - try_unpack_domain_specific_value(ADDRESS_KEY, &canonical_inner.domain_specific_fields)?; - - // unpack the pool id - let id: u64 = - try_unpack_domain_specific_value(ID_KEY, &canonical_inner.domain_specific_fields)?; - - // unpack the future pool governor - let future_pool_governor: String = try_unpack_domain_specific_value( - FUTURE_POOL_GOVERNOR_KEY, - &canonical_inner.domain_specific_fields, - )?; - - // unpack the pool params - let pool_params: Option = try_unpack_domain_specific_value( - POOL_PARAMS_KEY, - &canonical_inner.domain_specific_fields, - )?; - - // unpack the shares denom and total shares amount before combining them to a proto coin - let shares_denom: String = try_unpack_domain_specific_value( - SHARES_DENOM_KEY, - &canonical_inner.domain_specific_fields, - )?; - let shares_coin = Coin { - denom: shares_denom, - amount: canonical_inner.total_shares, - }; - - // unpack the total weight - let total_weight: String = try_unpack_domain_specific_value( - TOTAL_WEIGHT_KEY, - &canonical_inner.domain_specific_fields, - )?; + // unpack domain specific fields from inner type + let address: String = inner.get_domain_specific_field(ADDRESS_KEY)?; + let id: u64 = inner.get_domain_specific_field(ID_KEY)?; + let future_pool_governor: String = + inner.get_domain_specific_field(FUTURE_POOL_GOVERNOR_KEY)?; + let pool_params: Option = inner.get_domain_specific_field(POOL_PARAMS_KEY)?; + let shares_denom: String = inner.get_domain_specific_field(SHARES_DENOM_KEY)?; + let total_weight: String = inner.get_domain_specific_field(TOTAL_WEIGHT_KEY)?; // unpack the pool assets let mut pool_assets = vec![]; - for asset in &canonical_inner.assets { + for asset in &inner.assets { let pool_asset = PoolAsset { token: Some(Coin { denom: asset.denom.to_string(), amount: asset.amount.into(), }), - weight: try_unpack_domain_specific_value( - &format!("pool_asset_{}_weight", asset.denom), - &canonical_inner.domain_specific_fields, - )?, + weight: inner + .get_domain_specific_field(&format!("pool_asset_{}_weight", asset.denom))?, }; pool_assets.push(pool_asset); } @@ -140,7 +110,10 @@ impl ValenceTypeAdapter for OsmosisXykPool { id, pool_params, future_pool_governor, - total_shares: Some(shares_coin), + total_shares: Some(Coin { + denom: shares_denom, + amount: inner.total_shares, + }), pool_assets, total_weight, }) diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs index b600e369..77645cf8 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -8,10 +8,6 @@ use valence_middleware_utils::register_types; pub mod bank_balance; pub mod gamm_pool; -// TODO: embed the previously deployed version identifier there -// to ensure that types declared here implement a 1-1 mapper from -// the outdated version to this one. - // thought: these definitions could also be treated as optional fields. // e.g. not every type needs to be ICQ-able, so some types could miss // the ICQ adapter implementation. If registry receives an ICQ request @@ -25,15 +21,17 @@ pub mod gamm_pool; register_types! { "/osmosis.gamm.v1beta1.Pool" => { + // in the future, further plugins can be added here to handle type-specific + // logic. e.g. a migration plugin that would handle the type conversion + // from the type defined in the previous (semver) type registry: + // migrate_from: osmo_25_0_0::Pool, native_type: Pool, adapter: OsmosisXykPool, to_valence: ValenceType::XykPool, - // migrate_from: osmo_25_0_0::Pool, }, "/cosmos.bank.v1beta1.QueryBalanceResponse" => { native_type: QueryBalanceResponse, adapter: OsmosisBankBalance, to_valence: ValenceType::BankBalance, - // migrate_from: osmo_25_0_0::QueryBalanceResponse, } } diff --git a/packages/middleware-utils/src/canonical_types/pools/xyk.rs b/packages/middleware-utils/src/canonical_types/pools/xyk.rs index 35fd1ffd..baa2fa2d 100644 --- a/packages/middleware-utils/src/canonical_types/pools/xyk.rs +++ b/packages/middleware-utils/src/canonical_types/pools/xyk.rs @@ -1,8 +1,10 @@ use std::collections::BTreeMap; -use cosmwasm_schema::cw_serde; +use cosmwasm_schema::{cw_serde, serde::de::DeserializeOwned}; use cosmwasm_std::{ensure, Binary, Coin, Decimal, StdError, StdResult}; +use crate::try_unpack_domain_specific_value; + #[cw_serde] pub struct ValenceXykPool { /// assets in the pool @@ -33,6 +35,13 @@ impl ValenceXykPool { Ok(Decimal::from_ratio(a, b)) } + + pub fn get_domain_specific_field(&self, key: &str) -> StdResult + where + T: DeserializeOwned, + { + try_unpack_domain_specific_value(key, &self.domain_specific_fields) + } } /* diff --git a/packages/middleware-utils/src/lib.rs b/packages/middleware-utils/src/lib.rs index bd36dd61..e1bba635 100644 --- a/packages/middleware-utils/src/lib.rs +++ b/packages/middleware-utils/src/lib.rs @@ -35,6 +35,9 @@ pub enum MiddlewareError { #[error("{0}")] SemverError(#[from] semver::Error), + + #[error("canonical type conversion error: {0}")] + CanonicalConversionError(String), } pub fn try_unpack_domain_specific_value( diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index a92dac12..099ececa 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -11,6 +11,9 @@ pub struct RegistryInstantiateMsg {} #[cw_serde] pub enum RegistryExecuteMsg {} +/// this is effectively the valence vm types that are enabled +/// on a system level. if a particular type is not defined here, +/// it cannot be used in programs. #[cw_serde] pub enum ValenceType { XykPool(ValenceXykPool), From 31ff6a4a9abe61798311fa992f4ede3244e3f48c Mon Sep 17 00:00:00 2001 From: bekauz Date: Thu, 19 Dec 2024 23:32:47 +0100 Subject: [PATCH 88/92] init middleware e2e test --- Cargo.lock | 3 + Cargo.toml | 2 +- .../osmo-26-0-0/src/definitions/mod.rs | 14 +- local-interchaintest/Cargo.toml | 3 + .../examples/middleware_icq_test.rs | 156 ++++++++++++++++++ 5 files changed, 166 insertions(+), 12 deletions(-) create mode 100644 local-interchaintest/examples/middleware_icq_test.rs diff --git a/Cargo.lock b/Cargo.lock index 8e194347..9aff925c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2571,6 +2571,9 @@ dependencies = [ "valence-icq-lib-utils", "valence-icq-querier", "valence-library-utils", + "valence-middleware-broker", + "valence-middleware-osmosis", + "valence-middleware-utils", "valence-neutron-ibc-transfer-library", "valence-osmosis-cl-lper", "valence-osmosis-cl-withdrawer", diff --git a/Cargo.toml b/Cargo.toml index df604a19..818c8996 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ valence-icq-querier = { path = "contracts/libraries/icq-querier # middleware valence-middleware-osmosis = { path = "contracts/middleware/type-registries/osmosis/osmo-26-0-0", features = ["library"] } -valence-middleware-broker = { path = "contracts/middleware/brokers", features = ["library"] } +valence-middleware-broker = { path = "contracts/middleware/broker", features = ["library"] } # our packages valence-account-utils = { path = "packages/account-utils" } diff --git a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs index 77645cf8..120b4ec1 100644 --- a/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs +++ b/contracts/middleware/type-registries/osmosis/osmo-26-0-0/src/definitions/mod.rs @@ -8,23 +8,15 @@ use valence_middleware_utils::register_types; pub mod bank_balance; pub mod gamm_pool; -// thought: these definitions could also be treated as optional fields. -// e.g. not every type needs to be ICQ-able, so some types could miss -// the ICQ adapter implementation. If registry receives an ICQ request -// regarding a type that does not have an ICQ adapter, we return a clear -// error saying that the type is not ICQ-able (and perhaps provide the -// functionality that is available). -// such optionality could also enable us to make use of the semver more -// extensively. for instance, the major/minor/patch versions could follow -// the upstream type, and various additions could be attached to the semver -// as pre-release identifiers. - register_types! { "/osmosis.gamm.v1beta1.Pool" => { // in the future, further plugins can be added here to handle type-specific // logic. e.g. a migration plugin that would handle the type conversion // from the type defined in the previous (semver) type registry: // migrate_from: osmo_25_0_0::Pool, + // or maybe some kind of encoder/decoder plugin that could be defined along + // the lines of: + // evm_encoder: EvmTypeEncoder, native_type: Pool, adapter: OsmosisXykPool, to_valence: ValenceType::XykPool, diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 17dcc6a3..561716ac 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -50,3 +50,6 @@ neutron-sdk = { workspace = true } valence-icq-querier = { workspace = true } valence-osmosis-type-registry = { workspace = true } valence-icq-lib-utils = { workspace = true } +valence-middleware-broker = { workspace = true } +valence-middleware-osmosis = { workspace = true } +valence-middleware-utils = { workspace = true } diff --git a/local-interchaintest/examples/middleware_icq_test.rs b/local-interchaintest/examples/middleware_icq_test.rs new file mode 100644 index 00000000..ec2ecef2 --- /dev/null +++ b/local-interchaintest/examples/middleware_icq_test.rs @@ -0,0 +1,156 @@ +use local_interchaintest::utils::{ + osmosis::gamm::setup_gamm_pool, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, +}; +use localic_std::{ + errors::LocalError, + modules::cosmwasm::{contract_execute, contract_instantiate}, + types::TransactionResponse, +}; +use log::info; +use std::{env, error::Error, time::Duration}; +use valence_middleware_utils::type_registry::types::RegistryInstantiateMsg; + +use localic_utils::{ + utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, + LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_DENOM, + OSMOSIS_CHAIN_NAME, +}; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let mut test_ctx = TestContextBuilder::default() + .with_unwrap_raw_logs(true) + .with_api_url(LOCAL_IC_API_URL) + .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) + .with_chain(ConfigChainBuilder::default_neutron().build()?) + .with_chain(ConfigChainBuilder::default_osmosis().build()?) + .with_chain(ConfigChainBuilder::default_gaia().build()?) + .with_log_file_path(LOGS_FILE_PATH) + .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) + .build()?; + + let ntrn_on_osmo_denom = test_ctx + .get_ibc_denom() + .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + let ntrn_to_osmo_connection_id = test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let _pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + + let current_dir = env::current_dir()?; + + let mut uploader = test_ctx.build_tx_upload_contracts(); + + let osmosis_type_registry_middleware_path = format!( + "{}/artifacts/valence_middleware_osmosis.wasm", + current_dir.display() + ); + + let osmosis_middleware_broker_path = format!( + "{}/artifacts/valence_middleware_broker.wasm", + current_dir.display() + ); + + std::thread::sleep(Duration::from_secs(2)); + + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&osmosis_type_registry_middleware_path)?; + + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&osmosis_middleware_broker_path)?; + + let type_registry_code_id = test_ctx + .get_contract() + .contract("valence_middleware_osmosis") + .get_cw() + .code_id + .unwrap(); + + let broker_code_id = test_ctx + .get_contract() + .contract("valence_middleware_broker") + .get_cw() + .code_id + .unwrap(); + + // instantiate broker + let broker_contract = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + broker_code_id, + &serde_json::to_string(&valence_middleware_broker::msg::InstantiateMsg {})?, + "broker", + None, + "", + )?; + println!("middleware broker address: {}", broker_contract.address); + + // instantiate type registry + let type_registry_contract = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + type_registry_code_id, + &serde_json::to_string(&RegistryInstantiateMsg {})?, + "type_registry", + None, + "", + )?; + + println!( + "type_registry_contract address: {}", + type_registry_contract.address + ); + + let set_registry_response = set_type_registry( + &test_ctx, + broker_contract.address, + type_registry_contract.address, + "26.0.0".to_string(), + )?; + + println!( + "type registry addition response: {:?}", + set_registry_response + ); + + Ok(()) +} + +pub fn set_type_registry( + test_ctx: &TestContext, + broker: String, + type_registry_addr: String, + type_registry_version: String, +) -> Result { + let set_registry_msg = valence_middleware_broker::msg::ExecuteMsg::SetRegistry { + version: type_registry_version.to_string(), + address: type_registry_addr, + }; + + let stringified_msg = serde_json::to_string(&set_registry_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + + info!("registering type registry v.{type_registry_version}"); + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &broker, + DEFAULT_KEY, + &stringified_msg, + "--amount 1000000untrn --gas 50000000", + ) +} From ee9411a3ab8e3c5cc62a81947e8c3544f2d31f25 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 20 Dec 2024 14:58:47 +0100 Subject: [PATCH 89/92] adjust icq querier to broker logic --- Cargo.lock | 4 +- contracts/libraries/icq-querier/Cargo.toml | 4 +- .../libraries/icq-querier/src/contract.rs | 162 +++------ contracts/libraries/icq-querier/src/msg.rs | 21 +- contracts/libraries/icq-querier/src/state.rs | 4 +- .../examples/interchain_querier.rs | 312 +++++++++--------- .../examples/middleware_icq_test.rs | 191 +++++++++-- 7 files changed, 383 insertions(+), 315 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9aff925c..4174e64f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5252,13 +5252,13 @@ dependencies = [ "cw20 2.0.0", "neutron-sdk", "serde-json-wasm 1.0.1", - "serde_json", "thiserror 1.0.69", "valence-icq-lib-utils", "valence-library-base", "valence-library-utils", "valence-macros", - "valence-osmosis-type-registry", + "valence-middleware-broker", + "valence-middleware-utils", ] [[package]] diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 415f8b9d..9418ce04 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -24,9 +24,9 @@ neutron-sdk = { workspace = true } serde-json-wasm = { version = "1.0.0", default-features = false } cw-storage-plus = { workspace = true } thiserror = { workspace = true } -serde_json = { workspace = true } -valence-osmosis-type-registry = { workspace = true } valence-icq-lib-utils = { workspace = true } +valence-middleware-broker = { workspace = true } +valence-middleware-utils = { workspace = true } [dev-dependencies] cw20 = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 2e15644e..666e3ce0 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -1,25 +1,24 @@ +use std::collections::BTreeMap; + #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, to_json_string, Binary, Deps, DepsMut, Env, MessageInfo, Order, Reply, - Response, StdError, StdResult, SubMsg, + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Order, Reply, Response, StdError, + StdResult, SubMsg, }; use neutron_sdk::{ bindings::{ msg::{MsgRegisterInterchainQueryResponse, NeutronMsg}, query::NeutronQuery, + types::KVKey, }, - interchain_queries::queries::get_raw_interchain_query_result, + interchain_queries::{queries::get_raw_interchain_query_result, types::QueryType}, sudo::msg::SudoMsg, }; -use serde_json::Value; -use valence_icq_lib_utils::{PendingQueryIdConfig, QueryMsg as DomainRegistryQueryMsg}; -use valence_icq_lib_utils::{ - QueryReconstructionResponse, QueryRegistrationInfoRequest as DomainRegistryQueryRequest, -}; +use valence_icq_lib_utils::PendingQueryIdConfig; -use valence_icq_lib_utils::QueryRegistrationInfoResponse; use valence_library_utils::error::LibraryError; +use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}; use crate::{ msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, QueryMsg}, @@ -52,114 +51,55 @@ pub fn execute( ) -> Result, LibraryError> { match msg { FunctionMsgs::RegisterKvQuery { - type_registry, - module, - query, - } => register_kv_query(deps, type_registry, module, query), - FunctionMsgs::AssertQueryResult { - query_id, - assertion, - } => assert_query_result(deps, query_id, assertion), - } -} - -fn assert_query_result( - deps: DepsMut, - query_id: u64, - assertion: Vec, // reverse polish notation -) -> Result, LibraryError> { - let query_result = QUERY_RESULTS.load(deps.storage, query_id)?; - - let mut stack = vec![]; - for token in assertion.clone() { - match token.as_str() { - // operators - "==" => { - let b = stack.pop().unwrap(); - let a = stack.pop().unwrap(); - stack.push((a == b).to_string()); - } - "!=" => { - let b = stack.pop().unwrap(); - let a = stack.pop().unwrap(); - stack.push((a != b).to_string()); - } - ">" => { - let b = stack.pop().unwrap(); - let a = stack.pop().unwrap(); - stack.push((a > b).to_string()); - } - "<" => { - let b = stack.pop().unwrap(); - let a = stack.pop().unwrap(); - stack.push((a < b).to_string()); - } - // TODO: bunch of stuff here is missing like &&, ||, etc. - // operands - _ => { - if token.starts_with('/') { - let result = query_result.pointer(&token).unwrap(); - stack.push(result.to_string()); - } else { - stack.push(token.to_string()); - } - } - } - } - - if stack.len() == 1 { - let val = stack.pop().unwrap(); - if val == "true" { - Ok(Response::default() - .add_attribute("query_result", "true") - .add_attribute("for_assertion", assertion.join(" "))) - } else { - Err(LibraryError::Std(StdError::generic_err(format!( - "assertion failed, stack is non empty: {:?}", - stack - )))) - } - } else { - Err(LibraryError::Std(StdError::generic_err(format!( - "assertion failed, stack is non empty: {:?}", - stack - )))) + broker_addr, + type_id, + connection_id, + params, + } => register_kv_query(deps, broker_addr, type_id, connection_id, params), } } fn register_kv_query( deps: DepsMut, - type_registry: String, - module: String, - query: serde_json::Map, + broker_addr: String, + type_id: String, + connection_id: String, + params: BTreeMap, ) -> Result, LibraryError> { - let query_registration_resp: QueryRegistrationInfoResponse = deps.querier.query_wasm_smart( - type_registry.to_string(), - &DomainRegistryQueryMsg::GetRegistrationConfig(DomainRegistryQueryRequest { - module: module.to_string(), - params: query, - }), + let query_kv_key: KVKey = deps.querier.query_wasm_smart( + broker_addr.to_string(), + &valence_middleware_broker::msg::QueryMsg { + registry_version: None, + query: RegistryQueryMsg::KVKey { + type_id: type_id.to_string(), + params, + }, + }, )?; - let query_cfg = PendingQueryIdConfig { - associated_domain_registry: type_registry, - query_type: module.to_string(), + let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { + query_type: QueryType::KV.into(), + keys: vec![query_kv_key], + transactions_filter: String::new(), + connection_id, + update_period: 5, }; // here the key is set to the resp.reply_id just to get to the reply handler. // it will get overriden by the actual query id in the reply handler. - ASSOCIATED_QUERY_IDS.save(deps.storage, query_registration_resp.reply_id, &query_cfg)?; + ASSOCIATED_QUERY_IDS.save( + deps.storage, + 1, + &PendingQueryIdConfig { + associated_domain_registry: broker_addr, + query_type: type_id, + }, + )?; // fire registration in a submsg to get the registered query id back - let submsg = SubMsg::reply_on_success( - query_registration_resp.registration_msg.clone(), - query_registration_resp.reply_id, - ); + let submsg = SubMsg::reply_on_success(kv_registration_msg, 1); - Ok(Response::default().add_submessage(submsg).add_attribute( - "query_registration_response".to_string(), - to_json_string(&query_registration_resp)?, - )) + Ok(Response::default().add_submessage(submsg)) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -214,19 +154,23 @@ fn handle_sudo_kv_query_result( let pending_query_config = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; - let json_response: QueryReconstructionResponse = deps.querier.query_wasm_smart( + let reconstruction_response: NativeTypeWrapper = deps.querier.query_wasm_smart( pending_query_config.associated_domain_registry, - &DomainRegistryQueryMsg::ReconstructQuery( - valence_icq_lib_utils::QueryReconstructionRequest { + &valence_middleware_broker::msg::QueryMsg { + registry_version: None, + query: RegistryQueryMsg::ReconstructProto { + query_id: pending_query_config.query_type, icq_result: registered_query_result.result, - query_type: pending_query_config.query_type, }, - ), + }, )?; - QUERY_RESULTS.save(deps.storage, query_id, &json_response.json_value)?; + QUERY_RESULTS.save(deps.storage, query_id, &reconstruction_response.binary)?; - Ok(Response::new().add_attribute("query_result", json_response.json_value.to_string())) + Ok(Response::new().add_attribute( + "query_result", + to_json_binary(&reconstruction_response)?.to_string(), + )) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index 2d077686..c352d1ec 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -1,8 +1,10 @@ +use std::collections::BTreeMap; + use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Deps, DepsMut}; +use cosmwasm_std::{Addr, Binary, Deps, DepsMut}; use cw_ownable::cw_ownable_query; -use serde_json::Value; + use valence_library_utils::{error::LibraryError, msg::LibraryConfigValidation}; use valence_macros::{valence_library_query, ValenceLibraryInterface}; @@ -12,15 +14,10 @@ pub struct InstantiateMsg {} #[cw_serde] pub enum FunctionMsgs { RegisterKvQuery { - module: String, - // address of the target domain type registry contract - type_registry: String, - // json string of the query - query: serde_json::Map, - }, - AssertQueryResult { - query_id: u64, - assertion: Vec, + broker_addr: String, + type_id: String, + connection_id: String, + params: BTreeMap, }, } @@ -32,7 +29,7 @@ pub enum QueryMsg { #[returns(Vec<(u64, String)>)] RegisteredQueries {}, - #[returns(Vec<(u64, Value)>)] + #[returns(Vec<(u64, Binary)>)] QueryResults {}, } diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index f2ebbee5..6d047433 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -1,6 +1,6 @@ +use cosmwasm_std::Binary; use cw_storage_plus::Map; -use serde_json::Value; use valence_icq_lib_utils::PendingQueryIdConfig; pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); -pub const QUERY_RESULTS: Map = Map::new("query_results"); +pub const QUERY_RESULTS: Map = Map::new("query_results"); diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs index 15995c8a..0460531d 100644 --- a/local-interchaintest/examples/interchain_querier.rs +++ b/local-interchaintest/examples/interchain_querier.rs @@ -146,166 +146,166 @@ fn main() -> Result<(), Box> { println!("json gamm query: {:?}", gamm_query_params); - let kvq_registration_response = register_kvq( - &test_ctx, - icq_test_lib.address.to_string(), - osmo_domain_registry.address.to_string(), - osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), - gamm_query_params.as_object().unwrap().clone(), - )?; - - info!( - "kv query registration response: {:?}", - kvq_registration_response - ); - - std::thread::sleep(Duration::from_secs(2)); - - let bank_query_params = json!({ - "addr": OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), - "denom": OSMOSIS_CHAIN_DENOM.to_string(), - }); - - println!("json bank query: {:?}", bank_query_params); - - let kvq_registration_response = register_kvq( - &test_ctx, - icq_test_lib.address.to_string(), - osmo_domain_registry.address.to_string(), - osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::TYPE_URL.to_string(), - bank_query_params.as_object().unwrap().clone(), - )?; - - info!( - "kv query registration response: {:?}", - kvq_registration_response - ); - - let mut results_found = false; - let mut results = vec![]; - while !results_found { - results = query_results(&test_ctx, icq_test_lib.address.to_string())?; - - if results.len() == 2 { - info!("results: {:?}", results); - results_found = true; - } else { - info!("no results yet; sleeping for 3..."); - std::thread::sleep(Duration::from_secs(3)); - } - } - - let resp_1 = assert_icq_result( - &test_ctx, - icq_test_lib.address.to_string(), - results[0].0, - vec![ - "/pool_assets/0/token/amount".to_string(), - "/pool_assets/1/token/amount".to_string(), - "==".to_string(), - ], - )?; - - std::thread::sleep(Duration::from_secs(3)); - info!("assertion #1 result: {:?}", resp_1); - - let balance_amount: String = results[1] - .1 - .pointer("/coins/0/amount") - .unwrap() - .as_str() - .unwrap() - .to_string(); - info!("passing balance for assertion: {balance_amount}"); - let resp_2 = assert_icq_result( - &test_ctx, - icq_test_lib.address.to_string(), - results[1].0, - vec![ - "/coins/0/amount".to_string(), - balance_amount, // passing true - "==".to_string(), - ], - )?; - std::thread::sleep(Duration::from_secs(3)); - - info!("assertion #2 result: {:?}", resp_2); - - let resp_3 = assert_icq_result( - &test_ctx, - icq_test_lib.address.to_string(), - results[1].0, - vec![ - "/coins/0/amount".to_string(), - "314".to_string(), // passing false assertion value - "==".to_string(), - ], - )?; - std::thread::sleep(Duration::from_secs(3)); - - info!("assertion #3 result: {:?}", resp_3); + // let kvq_registration_response = register_kvq( + // &test_ctx, + // icq_test_lib.address.to_string(), + // osmo_domain_registry.address.to_string(), + // osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), + // gamm_query_params.as_object().unwrap().clone(), + // )?; + + // info!( + // "kv query registration response: {:?}", + // kvq_registration_response + // ); + + // std::thread::sleep(Duration::from_secs(2)); + + // let bank_query_params = json!({ + // "addr": OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), + // "denom": OSMOSIS_CHAIN_DENOM.to_string(), + // }); + + // println!("json bank query: {:?}", bank_query_params); + + // let kvq_registration_response = register_kvq( + // &test_ctx, + // icq_test_lib.address.to_string(), + // osmo_domain_registry.address.to_string(), + // osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::TYPE_URL.to_string(), + // bank_query_params.as_object().unwrap().clone(), + // )?; + + // info!( + // "kv query registration response: {:?}", + // kvq_registration_response + // ); + + // let mut results_found = false; + // let mut results = vec![]; + // while !results_found { + // results = query_results(&test_ctx, icq_test_lib.address.to_string())?; + + // if results.len() == 2 { + // info!("results: {:?}", results); + // results_found = true; + // } else { + // info!("no results yet; sleeping for 3..."); + // std::thread::sleep(Duration::from_secs(3)); + // } + // } + + // let resp_1 = assert_icq_result( + // &test_ctx, + // icq_test_lib.address.to_string(), + // results[0].0, + // vec![ + // "/pool_assets/0/token/amount".to_string(), + // "/pool_assets/1/token/amount".to_string(), + // "==".to_string(), + // ], + // )?; + + // std::thread::sleep(Duration::from_secs(3)); + // info!("assertion #1 result: {:?}", resp_1); + + // let balance_amount: String = results[1] + // .1 + // .pointer("/coins/0/amount") + // .unwrap() + // .as_str() + // .unwrap() + // .to_string(); + // info!("passing balance for assertion: {balance_amount}"); + // let resp_2 = assert_icq_result( + // &test_ctx, + // icq_test_lib.address.to_string(), + // results[1].0, + // vec![ + // "/coins/0/amount".to_string(), + // balance_amount, // passing true + // "==".to_string(), + // ], + // )?; + // std::thread::sleep(Duration::from_secs(3)); + + // info!("assertion #2 result: {:?}", resp_2); + + // let resp_3 = assert_icq_result( + // &test_ctx, + // icq_test_lib.address.to_string(), + // results[1].0, + // vec![ + // "/coins/0/amount".to_string(), + // "314".to_string(), // passing false assertion value + // "==".to_string(), + // ], + // )?; + // std::thread::sleep(Duration::from_secs(3)); + + // info!("assertion #3 result: {:?}", resp_3); Ok(()) } -pub fn assert_icq_result( - test_ctx: &TestContext, - icq_lib: String, - query_id: u64, - assertion: Vec, -) -> Result { - let icq_assertion_msg = FunctionMsgs::AssertQueryResult { - query_id, - assertion, - }; - - let stringified_msg = serde_json::to_string(&icq_assertion_msg) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?; - - info!("asserting query {query_id} result: {stringified_msg}"); - - contract_execute( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - DEFAULT_KEY, - &stringified_msg, - "--amount 1000000untrn --gas 50000000", - ) -} - -pub fn register_kvq( - test_ctx: &TestContext, - icq_lib: String, - type_registry: String, - module: String, - query: serde_json::Map, -) -> Result { - let register_kvq_msg = FunctionMsgs::RegisterKvQuery { - type_registry, - module, - query, - }; - - let stringified_msg = serde_json::to_string(®ister_kvq_msg) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?; - - info!( - "registering ICQ KV query on querier {icq_lib} : {:?}", - stringified_msg - ); - - contract_execute( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - DEFAULT_KEY, - &stringified_msg, - "--amount 1000000untrn --gas 50000000", - ) -} +// pub fn assert_icq_result( +// test_ctx: &TestContext, +// icq_lib: String, +// query_id: u64, +// assertion: Vec, +// ) -> Result { +// let icq_assertion_msg = FunctionMsgs::AssertQueryResult { +// query_id, +// assertion, +// }; + +// let stringified_msg = serde_json::to_string(&icq_assertion_msg) +// .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + +// info!("asserting query {query_id} result: {stringified_msg}"); + +// contract_execute( +// test_ctx +// .get_request_builder() +// .get_request_builder(NEUTRON_CHAIN_NAME), +// &icq_lib, +// DEFAULT_KEY, +// &stringified_msg, +// "--amount 1000000untrn --gas 50000000", +// ) +// } + +// pub fn register_kvq( +// test_ctx: &TestContext, +// icq_lib: String, +// type_registry: String, +// module: String, +// query: serde_json::Map, +// ) -> Result { +// let register_kvq_msg = FunctionMsgs::RegisterKvQuery { +// type_registry, +// module, +// query, +// }; + +// let stringified_msg = serde_json::to_string(®ister_kvq_msg) +// .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + +// info!( +// "registering ICQ KV query on querier {icq_lib} : {:?}", +// stringified_msg +// ); + +// contract_execute( +// test_ctx +// .get_request_builder() +// .get_request_builder(NEUTRON_CHAIN_NAME), +// &icq_lib, +// DEFAULT_KEY, +// &stringified_msg, +// "--amount 1000000untrn --gas 50000000", +// ) +// } pub fn query_results( test_ctx: &TestContext, diff --git a/local-interchaintest/examples/middleware_icq_test.rs b/local-interchaintest/examples/middleware_icq_test.rs index ec2ecef2..346f5d24 100644 --- a/local-interchaintest/examples/middleware_icq_test.rs +++ b/local-interchaintest/examples/middleware_icq_test.rs @@ -1,13 +1,17 @@ +use cosmwasm_std::{to_json_binary, Binary}; use local_interchaintest::utils::{ - osmosis::gamm::setup_gamm_pool, LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, + icq::{generate_icq_relayer_config, start_icq_relayer}, + osmosis::gamm::setup_gamm_pool, + LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, }; use localic_std::{ errors::LocalError, - modules::cosmwasm::{contract_execute, contract_instantiate}, + modules::cosmwasm::{contract_execute, contract_instantiate, contract_query}, types::TransactionResponse, }; use log::info; -use std::{env, error::Error, time::Duration}; +use std::{collections::BTreeMap, env, error::Error, time::Duration}; +use valence_icq_querier::msg::FunctionMsgs; use valence_middleware_utils::type_registry::types::RegistryInstantiateMsg; use localic_utils::{ @@ -36,67 +40,82 @@ fn main() -> Result<(), Box> { .src(NEUTRON_CHAIN_NAME) .dest(OSMOSIS_CHAIN_NAME) .get(); - let ntrn_to_osmo_connection_id = test_ctx - .get_connections() - .src(NEUTRON_CHAIN_NAME) - .dest(OSMOSIS_CHAIN_NAME) - .get(); - let _pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; + let pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; let current_dir = env::current_dir()?; + // with test context set up, we can generate the .env file for the icq relayer + generate_icq_relayer_config( + &test_ctx, + current_dir.clone(), + OSMOSIS_CHAIN_NAME.to_string(), + )?; + + // start the icq relayer. this runs in detached mode so we need + // to manually kill it before each run for now. + start_icq_relayer()?; + let mut uploader = test_ctx.build_tx_upload_contracts(); let osmosis_type_registry_middleware_path = format!( "{}/artifacts/valence_middleware_osmosis.wasm", current_dir.display() ); - let osmosis_middleware_broker_path = format!( "{}/artifacts/valence_middleware_broker.wasm", current_dir.display() ); + let icq_lib_local_path = format!( + "{}/artifacts/valence_icq_querier.wasm", + current_dir.display() + ); - std::thread::sleep(Duration::from_secs(2)); + info!("sleeping for 5 to allow icq relayer to start..."); + std::thread::sleep(Duration::from_secs(10)); + uploader + .with_chain_name(NEUTRON_CHAIN_NAME) + .send_single_contract(&icq_lib_local_path)?; + std::thread::sleep(Duration::from_secs(1)); uploader .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&osmosis_type_registry_middleware_path)?; - + std::thread::sleep(Duration::from_secs(1)); uploader .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&osmosis_middleware_broker_path)?; + std::thread::sleep(Duration::from_secs(1)); - let type_registry_code_id = test_ctx - .get_contract() - .contract("valence_middleware_osmosis") - .get_cw() - .code_id - .unwrap(); - - let broker_code_id = test_ctx + // set up the ICQ querier + let icq_querier_lib_code_id = test_ctx .get_contract() - .contract("valence_middleware_broker") + .contract("valence_icq_querier") .get_cw() .code_id .unwrap(); - - // instantiate broker - let broker_contract = contract_instantiate( + let icq_test_lib = contract_instantiate( test_ctx .get_request_builder() .get_request_builder(NEUTRON_CHAIN_NAME), DEFAULT_KEY, - broker_code_id, - &serde_json::to_string(&valence_middleware_broker::msg::InstantiateMsg {})?, - "broker", + icq_querier_lib_code_id, + &serde_json::to_string(&valence_icq_querier::msg::InstantiateMsg {})?, + "icq_querier_lib", None, "", )?; - println!("middleware broker address: {}", broker_contract.address); + info!("icq querier lib address: {}", icq_test_lib.address); + + std::thread::sleep(Duration::from_secs(3)); - // instantiate type registry + // set up the type registry + let type_registry_code_id = test_ctx + .get_contract() + .contract("valence_middleware_osmosis") + .get_cw() + .code_id + .unwrap(); let type_registry_contract = contract_instantiate( test_ctx .get_request_builder() @@ -109,22 +128,76 @@ fn main() -> Result<(), Box> { "", )?; - println!( + info!( "type_registry_contract address: {}", type_registry_contract.address ); + std::thread::sleep(Duration::from_secs(3)); + // set up the broker + let broker_code_id = test_ctx + .get_contract() + .contract("valence_middleware_broker") + .get_cw() + .code_id + .unwrap(); + let broker_contract = contract_instantiate( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + DEFAULT_KEY, + broker_code_id, + &serde_json::to_string(&valence_middleware_broker::msg::InstantiateMsg {})?, + "broker", + None, + "", + )?; + info!("middleware broker address: {}", broker_contract.address); + std::thread::sleep(Duration::from_secs(3)); + + // associate type registry with broker let set_registry_response = set_type_registry( &test_ctx, - broker_contract.address, + broker_contract.address.to_string(), type_registry_contract.address, "26.0.0".to_string(), )?; - println!( + info!( "type registry addition response: {:?}", set_registry_response ); + std::thread::sleep(Duration::from_secs(2)); + + let gamm_query_params = + BTreeMap::from([("pool_id".to_string(), to_json_binary(&pool_id).unwrap())]); + + let ntrn_to_osmo_connection_id = test_ctx + .get_connections() + .src(NEUTRON_CHAIN_NAME) + .dest(OSMOSIS_CHAIN_NAME) + .get(); + + let kvq_registration_response = register_kvq( + &test_ctx, + icq_test_lib.address.to_string(), + broker_contract.address.to_string(), + osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), + ntrn_to_osmo_connection_id, + gamm_query_params, + )?; + + info!( + "KEY VALUE QUERY REGISTRATION RESPONSE TXHASH: {}", + kvq_registration_response.tx_hash.unwrap() + ); + + std::thread::sleep(Duration::from_secs(10)); + + info!("querying results..."); + let query_results_response = query_results(&test_ctx, icq_test_lib.address.to_string())?; + + info!("query results: {:?}", query_results_response); Ok(()) } @@ -154,3 +227,57 @@ pub fn set_type_registry( "--amount 1000000untrn --gas 50000000", ) } + +pub fn register_kvq( + test_ctx: &TestContext, + icq_lib: String, + broker_addr: String, + type_id: String, + connection_id: String, + params: BTreeMap, +) -> Result { + let register_kvq_msg = FunctionMsgs::RegisterKvQuery { + broker_addr, + type_id, + connection_id, + params, + }; + + let stringified_msg = serde_json::to_string(®ister_kvq_msg) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?; + + info!( + "registering ICQ KV query on querier {icq_lib} : {:?}", + stringified_msg + ); + + contract_execute( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + DEFAULT_KEY, + &stringified_msg, + "--amount 1000000untrn --gas 50000000", + ) +} + +pub fn query_results( + test_ctx: &TestContext, + icq_lib: String, +) -> Result, LocalError> { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &icq_lib, + &serde_json::to_string(&valence_icq_querier::msg::QueryMsg::QueryResults {}) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + println!("query response: {:?}", query_response); + let resp: Vec<(u64, Binary)> = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} From 579f11bff7d40bf12bc92901ef838480dd934e21 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 20 Dec 2024 15:15:08 +0100 Subject: [PATCH 90/92] e2e run to getting valence type and querying the price --- .../examples/middleware_icq_test.rs | 48 ++++++++++++++++++- local-interchaintest/src/utils/osmosis.rs | 2 +- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/local-interchaintest/examples/middleware_icq_test.rs b/local-interchaintest/examples/middleware_icq_test.rs index 346f5d24..248ba216 100644 --- a/local-interchaintest/examples/middleware_icq_test.rs +++ b/local-interchaintest/examples/middleware_icq_test.rs @@ -12,7 +12,9 @@ use localic_std::{ use log::info; use std::{collections::BTreeMap, env, error::Error, time::Duration}; use valence_icq_querier::msg::FunctionMsgs; -use valence_middleware_utils::type_registry::types::RegistryInstantiateMsg; +use valence_middleware_utils::type_registry::types::{ + RegistryInstantiateMsg, RegistryQueryMsg, ValenceType, +}; use localic_utils::{ utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, @@ -199,6 +201,25 @@ fn main() -> Result<(), Box> { info!("query results: {:?}", query_results_response); + let hopefully_proto_gamm_pool = query_results_response[0].1.clone(); + + let valence_xyk_pool = broker_get_canonical( + &test_ctx, + broker_contract.address.to_string(), + osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), + hopefully_proto_gamm_pool, + )?; + + info!("valence xyk pool: {:?}", valence_xyk_pool); + + match valence_xyk_pool { + ValenceType::XykPool(valence_xyk_pool) => { + let price = valence_xyk_pool.get_price(); + info!("price: {:?}", price); + } + _ => panic!("should be xyk pool"), + }; + Ok(()) } @@ -281,3 +302,28 @@ pub fn query_results( Ok(resp) } + +pub fn broker_get_canonical( + test_ctx: &TestContext, + broker_addr: String, + type_url: String, + binary: Binary, +) -> Result { + let query_response = contract_query( + test_ctx + .get_request_builder() + .get_request_builder(NEUTRON_CHAIN_NAME), + &broker_addr, + &serde_json::to_string(&valence_middleware_broker::msg::QueryMsg { + registry_version: None, + query: RegistryQueryMsg::ToCanonical { type_url, binary }, + }) + .map_err(|e| LocalError::Custom { msg: e.to_string() })?, + )["data"] + .clone(); + + println!("query response: {:?}", query_response); + let resp: ValenceType = serde_json::from_value(query_response).unwrap(); + + Ok(resp) +} diff --git a/local-interchaintest/src/utils/osmosis.rs b/local-interchaintest/src/utils/osmosis.rs index 99778b97..c60cd188 100644 --- a/local-interchaintest/src/utils/osmosis.rs +++ b/local-interchaintest/src/utils/osmosis.rs @@ -35,7 +35,7 @@ pub mod gamm { .build_tx_create_osmo_pool() .with_weight(denom_1, 1) .with_weight(denom_2, 1) - .with_initial_deposit(denom_1, 100_000_000) + .with_initial_deposit(denom_1, 120_000_000) .with_initial_deposit(denom_2, 100_000_000) .send()?; From 81308f839184d4da68240451045d01c8e0a7b2d3 Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 20 Dec 2024 15:53:30 +0100 Subject: [PATCH 91/92] remove old type registry --- Cargo.lock | 22 -- Cargo.toml | 3 - .../osmo_registry/Cargo.toml | 34 -- .../osmo_registry/src/contract.rs | 92 ----- .../osmo_registry/src/lib.rs | 7 - .../osmo_registry/src/msg.rs | 19 - .../osmo_registry/src/state.rs | 4 - .../osmo_registry/src/testing/mod.rs | 1 - .../osmo_registry/src/testing/tests.rs | 59 ---- .../bank_v1beta1_query_balance.rs | 102 ------ .../src/type_definitions/gamm_v1beta1_pool.rs | 42 --- .../osmo_registry/src/type_definitions/mod.rs | 2 - contracts/libraries/icq-querier/Cargo.toml | 28 +- local-interchaintest/Cargo.toml | 1 - .../examples/interchain_querier.rs | 327 ------------------ 15 files changed, 14 insertions(+), 729 deletions(-) delete mode 100644 contracts/domain_type_registries/osmo_registry/Cargo.toml delete mode 100644 contracts/domain_type_registries/osmo_registry/src/contract.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/lib.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/msg.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/state.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/testing/mod.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/testing/tests.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs delete mode 100644 contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs delete mode 100644 local-interchaintest/examples/interchain_querier.rs diff --git a/Cargo.lock b/Cargo.lock index 4174e64f..fd6d9a2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2579,7 +2579,6 @@ dependencies = [ "valence-osmosis-cl-withdrawer", "valence-osmosis-gamm-lper", "valence-osmosis-gamm-withdrawer", - "valence-osmosis-type-registry", "valence-osmosis-utils", "valence-processor", "valence-processor-utils", @@ -5473,27 +5472,6 @@ dependencies = [ "valence-osmosis-utils", ] -[[package]] -name = "valence-osmosis-type-registry" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema 2.1.4", - "cosmwasm-std 2.1.4", - "cw-ownable", - "cw-storage-plus 2.0.0", - "cw20 2.0.0", - "neutron-sdk", - "osmosis-std", - "osmosis-test-tube", - "prost 0.13.3", - "prost-types 0.13.3", - "serde-json-wasm 1.0.1", - "serde_json", - "thiserror 1.0.69", - "valence-icq-lib-utils", - "valence-osmosis-utils", -] - [[package]] name = "valence-osmosis-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 818c8996..7b337845 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,9 +97,6 @@ valence-program-registry = { path = "contracts/program-registry", features valence-icq-lib-utils = { path = "packages/icq-querier-utils" } valence-middleware-utils = { path = "packages/middleware-utils" } -# domain type registries -valence-osmosis-type-registry = { path = "contracts/domain_type_registries/osmo_registry", features = ["library"] } - # dev-dependencies cw-multi-test = { version = "2.1.1", features = ["cosmwasm_1_4"] } cw20 = { version = "2.0.0" } diff --git a/contracts/domain_type_registries/osmo_registry/Cargo.toml b/contracts/domain_type_registries/osmo_registry/Cargo.toml deleted file mode 100644 index c741db58..00000000 --- a/contracts/domain_type_registries/osmo_registry/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "valence-osmosis-type-registry" -authors = { workspace = true } -edition = { workspace = true } -license = { workspace = true } -version = { workspace = true } -repository = { workspace = true } - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -# use library feature to disable all instantiate/execute/query exports -library = [] - -[dependencies] -cosmwasm-std = { workspace = true } -cosmwasm-schema = { workspace = true } -cw-ownable = { workspace = true } -osmosis-std = { workspace = true } -valence-osmosis-utils = { workspace = true } -prost = { version = "0.13.3", default-features = false, features = [ "prost-derive" ] } -prost-types = { version = "0.13.3", default-features = false } -neutron-sdk = { workspace = true } -serde-json-wasm = { version = "1.0.0", default-features = false } -cw-storage-plus = { workspace = true } -thiserror = { workspace = true } -serde_json = { workspace = true } -valence-icq-lib-utils = { workspace = true } - -[dev-dependencies] -cw20 = { workspace = true } -osmosis-test-tube = { workspace = true } -valence-osmosis-utils = { workspace = true, features = ["testing"] } diff --git a/contracts/domain_type_registries/osmo_registry/src/contract.rs b/contracts/domain_type_registries/osmo_registry/src/contract.rs deleted file mode 100644 index 8fe9c378..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/contract.rs +++ /dev/null @@ -1,92 +0,0 @@ -use std::str::FromStr; - -#[cfg(not(feature = "library"))] -use cosmwasm_std::entry_point; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; -use neutron_sdk::bindings::msg::NeutronMsg; -use neutron_sdk::interchain_queries::types::QueryType; -use valence_icq_lib_utils::QueryReconstructionRequest; -use valence_icq_lib_utils::QueryReconstructionResponse; -use valence_icq_lib_utils::QueryRegistrationInfoRequest; -use valence_icq_lib_utils::QueryRegistrationInfoResponse; -use valence_icq_lib_utils::TypeRegistryError; - -use crate::msg::DomainRegistryType; -use crate::state::CONNECTION_ID; - -use valence_icq_lib_utils::ExecuteMsg as DomainRegistryExecuteMsg; -use valence_icq_lib_utils::InstantiateMsg as DomainRegistryInstantiateMsg; -use valence_icq_lib_utils::QueryMsg as DomainRegistryQueryMsg; - -// version info for migration info -const _CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); -const _CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: DomainRegistryInstantiateMsg, -) -> Result { - CONNECTION_ID.save(deps.storage, &msg.connection_id)?; - - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: DomainRegistryExecuteMsg, -) -> Result { - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: DomainRegistryQueryMsg) -> StdResult { - match msg { - DomainRegistryQueryMsg::GetRegistrationConfig(request) => { - get_registration_config(deps, request) - } - DomainRegistryQueryMsg::ReconstructQuery(query_reconstruction_request) => { - reconstruct_icq_result(query_reconstruction_request) - } - } -} - -fn reconstruct_icq_result(query: QueryReconstructionRequest) -> StdResult { - let underlying_type = DomainRegistryType::from_str(&query.query_type)?; - - let reconstructed_json_value = underlying_type.reconstruct_response(&query)?; - - let resp = QueryReconstructionResponse { - json_value: reconstructed_json_value, - }; - - to_json_binary(&resp) -} - -fn get_registration_config(deps: Deps, query: QueryRegistrationInfoRequest) -> StdResult { - let osmo_type = DomainRegistryType::from_str(&query.module)?; - - let (kv_key, response_code_id) = osmo_type.get_registration_config(query.params)?; - - let connection_id = CONNECTION_ID.load(deps.storage)?; - - let kv_registration_msg = NeutronMsg::RegisterInterchainQuery { - query_type: QueryType::KV.into(), - keys: vec![kv_key], - transactions_filter: String::new(), - connection_id, - update_period: 5, - }; - - let query = QueryRegistrationInfoResponse { - registration_msg: kv_registration_msg, - reply_id: response_code_id, - }; - - to_json_binary(&query) -} diff --git a/contracts/domain_type_registries/osmo_registry/src/lib.rs b/contracts/domain_type_registries/osmo_registry/src/lib.rs deleted file mode 100644 index 1bbe50c6..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod contract; -pub mod msg; -#[cfg(test)] -mod testing; - -pub mod state; -pub mod type_definitions; diff --git a/contracts/domain_type_registries/osmo_registry/src/msg.rs b/contracts/domain_type_registries/osmo_registry/src/msg.rs deleted file mode 100644 index bfac1cad..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/msg.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::str::FromStr; - -use cosmwasm_schema::cw_serde; -use cosmwasm_std::StdResult; -use neutron_sdk::bindings::types::KVKey; -use serde_json::Value; -use valence_icq_lib_utils::{define_registry_types, QueryReconstructionRequest}; - -pub trait QueryTypeDefinition { - const REPLY_ID: u64; - - fn get_kv_key(&self, params: serde_json::Map) -> StdResult; - fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult; -} - -define_registry_types! { - (GammV1Beta1Pool, osmosis_std::types::osmosis::gamm::v1beta1::Pool), - (BankV1Beta1Balance, osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse) -} diff --git a/contracts/domain_type_registries/osmo_registry/src/state.rs b/contracts/domain_type_registries/osmo_registry/src/state.rs deleted file mode 100644 index 276d052c..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/state.rs +++ /dev/null @@ -1,4 +0,0 @@ -use cw_storage_plus::Item; - -// connection id from home domain to osmosis -pub const CONNECTION_ID: Item = Item::new("connection_id"); diff --git a/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs b/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs deleted file mode 100644 index 14f00389..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/testing/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod tests; diff --git a/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs b/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs deleted file mode 100644 index 73d3dc80..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/testing/tests.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::msg::QueryTypeDefinition; - -use serde_json::{json, Value}; - -#[test] -fn test_balance_get_kv_key() { - let balance = osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::default(); - let params = json!({ - "addr": "osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63", - "denom": "uosmo" - }); - - let param_map = params.as_object().unwrap(); - - let _result = balance.get_kv_key(param_map.clone()).unwrap(); -} - -#[test] -fn test_json_map_serde() { - let params = json!({ - "pool_id": "1" - }); - - let json_restored: serde_json::Map = params.as_object().unwrap().clone(); - println!("json restored: {:?}", json_restored); - - let pool_id = json_restored["pool_id"].as_u64().unwrap(); - - println!("pool_id: {:?}", pool_id); -} - -#[test] -fn test_gamm_pool_get_kv_key() { - let pool = osmosis_std::types::osmosis::gamm::v1beta1::Pool::default(); - let params = json!({ - "pool_id": 1 - }); - - let param_str = params.to_string(); - - let json_restored: Value = serde_json::from_str(¶m_str).unwrap(); - println!("json restored: {:?}", json_restored); - - let pool_id = json_restored["pool_id"].as_u64().unwrap(); - - println!("pool_id: {:?}", pool_id); - - let param_map = params.as_object().unwrap(); - - let result = pool.get_kv_key(param_map.clone()).unwrap(); - - assert_eq!(result.path, "gamm"); - let expected_key = { - let mut key = vec![0x02]; - key.extend_from_slice(&1u64.to_be_bytes()); - key - }; - assert_eq!(result.key.as_slice(), expected_key.as_slice()); -} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs deleted file mode 100644 index 478a07a1..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/type_definitions/bank_v1beta1_query_balance.rs +++ /dev/null @@ -1,102 +0,0 @@ -use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; -use neutron_sdk::{ - bindings::types::KVKey, - interchain_queries::{ - helpers::decode_and_convert, - types::KVReconstruct, - v047::{helpers::create_account_denom_balance_key, types::BANK_STORE_KEY}, - }, -}; -use serde_json::Value; -use valence_icq_lib_utils::{get_str_query_param, QueryReconstructionRequest}; - -use crate::msg::QueryTypeDefinition; - -impl QueryTypeDefinition for osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse { - const REPLY_ID: u64 = 31416; - - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { - let addr = get_str_query_param(¶ms, "addr")?; - let denom = get_str_query_param(¶ms, "denom")?; - - let converted_addr_bytes = decode_and_convert(&addr) - .map_err(|_| StdError::generic_err("failed to decode addr"))?; - let balance_key = create_account_denom_balance_key(converted_addr_bytes, denom).unwrap(); - - Ok(KVKey { - path: BANK_STORE_KEY.to_string(), - key: Binary::new(balance_key), - }) - } - - fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { - let balances: neutron_sdk::interchain_queries::v047::types::Balances = - KVReconstruct::reconstruct(&request.icq_result.kv_results).map_err(|e| { - StdError::generic_err(format!("failed to reconstruct query result: {:?}", e)) - })?; - - let balances_str = to_json_string(&balances)?; - - let json_value: Value = serde_json::from_str(&balances_str) - .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; - - Ok(json_value) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use neutron_sdk::bindings::types::StorageValue; - use osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse; - use serde_json::json; - - #[test] - fn test_get_kv_key() { - let mut params = serde_json::Map::new(); - params.insert( - "addr".to_string(), - json!("osmo1hj5fveer5cjtn4wd6wstzugjfdxzl0xpwhpz63"), - ); - params.insert("denom".to_string(), json!("uosmo")); - - let qb_response = QueryBalanceResponse::default(); - let kvk_response = qb_response.get_kv_key(params).unwrap(); - - let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); - - assert_eq!(kvk_response.path, "bank".to_string()); - assert_eq!(kvk_response.key, key_binary); - } - - #[test] - fn test_decode_and_reconstruct() { - let key_binary = Binary::from_base64("AhS8qJZnI6YkudXN06CxcRJLTC+8wXVvc21v").unwrap(); - let value_binary = Binary::from_base64("OTk5ODg5OTk5NzUwMA==").unwrap(); - - let request = QueryReconstructionRequest { - icq_result: neutron_sdk::bindings::types::InterchainQueryResult { - kv_results: vec![StorageValue { - key: key_binary, - value: value_binary, - storage_prefix: "bank".to_string(), - }], - height: 1, - revision: 1, - }, - query_type: QueryBalanceResponse::TYPE_URL.to_string(), - }; - - let result = QueryBalanceResponse::decode_and_reconstruct(&request).unwrap(); - - let expected_json = json!({ - "coins": [ - { - "amount": "9998899997500", - "denom": "uosmo" - } - ] - }); - assert_eq!(result, expected_json); - } -} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs deleted file mode 100644 index f41f2fa9..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/type_definitions/gamm_v1beta1_pool.rs +++ /dev/null @@ -1,42 +0,0 @@ -use cosmwasm_std::{to_json_string, Binary, StdError, StdResult}; -use neutron_sdk::bindings::types::KVKey; -use osmosis_std::shim::Any; -use prost::Message; -use serde_json::Value; -use valence_icq_lib_utils::{get_u64_query_param, QueryReconstructionRequest}; - -use crate::msg::QueryTypeDefinition; - -impl QueryTypeDefinition for osmosis_std::types::osmosis::gamm::v1beta1::Pool { - const REPLY_ID: u64 = 31415; - - fn get_kv_key(&self, params: serde_json::Map) -> StdResult { - let pool_prefix_key: u8 = 0x02; - - let pool_id = get_u64_query_param(¶ms, "pool_id")?; - - let mut pool_access_key = vec![pool_prefix_key]; - pool_access_key.extend_from_slice(&pool_id.to_be_bytes()); - - Ok(KVKey { - path: "gamm".to_string(), - key: Binary::new(pool_access_key), - }) - } - - fn decode_and_reconstruct(request: &QueryReconstructionRequest) -> StdResult { - let any_msg: Any = Any::decode(request.icq_result.kv_results[0].value.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))?; - - let osmo_pool: osmosis_std::types::osmosis::gamm::v1beta1::Pool = any_msg - .try_into() - .map_err(|_| StdError::generic_err("failed to decode pool from any"))?; - - let json_str_pool = to_json_string(&osmo_pool)?; - - let json_value: Value = serde_json::from_str(&json_str_pool) - .map_err(|_e| StdError::generic_err("failed to obtain value from str"))?; - - Ok(json_value) - } -} diff --git a/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs b/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs deleted file mode 100644 index d478596e..00000000 --- a/contracts/domain_type_registries/osmo_registry/src/type_definitions/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod bank_v1beta1_query_balance; -pub mod gamm_v1beta1_pool; diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 9418ce04..1ae51823 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -14,19 +14,19 @@ crate-type = ["cdylib", "rlib"] library = [] [dependencies] -cosmwasm-std = { workspace = true } -cosmwasm-schema = { workspace = true } -cw-ownable = { workspace = true } -valence-macros = { workspace = true } -valence-library-utils = { workspace = true } -valence-library-base = { workspace = true } -neutron-sdk = { workspace = true } -serde-json-wasm = { version = "1.0.0", default-features = false } -cw-storage-plus = { workspace = true } -thiserror = { workspace = true } -valence-icq-lib-utils = { workspace = true } -valence-middleware-broker = { workspace = true } -valence-middleware-utils = { workspace = true } +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-ownable = { workspace = true } +valence-macros = { workspace = true } +valence-library-utils = { workspace = true } +valence-library-base = { workspace = true } +neutron-sdk = { workspace = true } +serde-json-wasm = { version = "1.0.0", default-features = false } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } +valence-icq-lib-utils = { workspace = true } +valence-middleware-broker = { workspace = true } +valence-middleware-utils = { workspace = true } [dev-dependencies] -cw20 = { workspace = true } +cw20 = { workspace = true } diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 561716ac..8a45d942 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -48,7 +48,6 @@ osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } valence-icq-querier = { workspace = true } -valence-osmosis-type-registry = { workspace = true } valence-icq-lib-utils = { workspace = true } valence-middleware-broker = { workspace = true } valence-middleware-osmosis = { workspace = true } diff --git a/local-interchaintest/examples/interchain_querier.rs b/local-interchaintest/examples/interchain_querier.rs deleted file mode 100644 index 0460531d..00000000 --- a/local-interchaintest/examples/interchain_querier.rs +++ /dev/null @@ -1,327 +0,0 @@ -use local_interchaintest::utils::{ - icq::{generate_icq_relayer_config, start_icq_relayer}, - osmosis::gamm::setup_gamm_pool, - LOGS_FILE_PATH, VALENCE_ARTIFACTS_PATH, -}; -use localic_std::{ - errors::LocalError, - modules::cosmwasm::{contract_execute, contract_instantiate, contract_query}, - types::TransactionResponse, -}; -use log::info; -use serde_json::{json, Value}; -use std::{env, error::Error, time::Duration}; -use valence_icq_querier::msg::{FunctionMsgs, InstantiateMsg, QueryMsg}; - -use localic_utils::{ - utils::test_context::TestContext, ConfigChainBuilder, TestContextBuilder, DEFAULT_KEY, - LOCAL_IC_API_URL, NEUTRON_CHAIN_DENOM, NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_ADMIN_ADDR, - OSMOSIS_CHAIN_DENOM, OSMOSIS_CHAIN_NAME, -}; - -// KeyNextGlobalPoolId defines key to store the next Pool ID to be used. -pub const NEXT_GLOBAL_POOL_ID_KEY: u8 = 0x01; -pub const PREFIX_POOLS_KEY: u8 = 0x02; -pub const TOTAL_LIQUIDITY_KEY: u8 = 0x03; -pub const PREFIX_MIGRATION_INFO_BALANCER_POOL_KEY: u8 = 0x04; -pub const GAMM_STORE_KEY: &str = "gamm"; - -fn main() -> Result<(), Box> { - env_logger::init(); - - let mut test_ctx = TestContextBuilder::default() - .with_unwrap_raw_logs(true) - .with_api_url(LOCAL_IC_API_URL) - .with_artifacts_dir(VALENCE_ARTIFACTS_PATH) - .with_chain(ConfigChainBuilder::default_neutron().build()?) - .with_chain(ConfigChainBuilder::default_osmosis().build()?) - .with_chain(ConfigChainBuilder::default_gaia().build()?) - .with_log_file_path(LOGS_FILE_PATH) - .with_transfer_channels(NEUTRON_CHAIN_NAME, OSMOSIS_CHAIN_NAME) - .build()?; - - let ntrn_on_osmo_denom = test_ctx - .get_ibc_denom() - .base_denom(NEUTRON_CHAIN_DENOM.to_owned()) - .src(NEUTRON_CHAIN_NAME) - .dest(OSMOSIS_CHAIN_NAME) - .get(); - - let _pool_id = setup_gamm_pool(&mut test_ctx, OSMOSIS_CHAIN_DENOM, &ntrn_on_osmo_denom)?; - - let current_dir = env::current_dir()?; - - // with test context set up, we can generate the .env file for the icq relayer - generate_icq_relayer_config( - &test_ctx, - current_dir.clone(), - OSMOSIS_CHAIN_NAME.to_string(), - )?; - - // start the icq relayer. this runs in detached mode so we need - // to manually kill it before each run for now. - start_icq_relayer()?; - - let mut uploader = test_ctx.build_tx_upload_contracts(); - let icq_lib_local_path = format!( - "{}/artifacts/valence_icq_querier.wasm", - current_dir.display() - ); - let osmo_domain_registry_local_path = format!( - "{}/artifacts/valence_osmosis_type_registry.wasm", - current_dir.display() - ); - - info!("sleeping to allow icq relayer to start..."); - std::thread::sleep(Duration::from_secs(10)); - - uploader - .with_chain_name(NEUTRON_CHAIN_NAME) - .send_single_contract(&icq_lib_local_path)?; - - uploader - .with_chain_name(NEUTRON_CHAIN_NAME) - .send_single_contract(&osmo_domain_registry_local_path)?; - - let icq_querier_lib_code_id = test_ctx - .get_contract() - .contract("valence_icq_querier") - .get_cw() - .code_id - .unwrap(); - - info!("icq querier library code id: {icq_querier_lib_code_id}"); - - let osmo_domain_registry_code_id = test_ctx - .get_contract() - .contract("valence_osmosis_type_registry") - .get_cw() - .code_id - .unwrap(); - - let ntrn_to_osmo_connection_id = test_ctx - .get_connections() - .src(NEUTRON_CHAIN_NAME) - .dest(OSMOSIS_CHAIN_NAME) - .get(); - - let osmo_domain_registry = contract_instantiate( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - DEFAULT_KEY, - osmo_domain_registry_code_id, - &serde_json::to_string(&valence_icq_lib_utils::InstantiateMsg { - connection_id: ntrn_to_osmo_connection_id, - })?, - "icq_querier_lib", - None, - "", - )?; - info!( - "osmo_domain_registry address: {}", - osmo_domain_registry.address - ); - - // instantiate icq querier lib - let icq_test_lib = contract_instantiate( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - DEFAULT_KEY, - icq_querier_lib_code_id, - &serde_json::to_string(&InstantiateMsg {})?, - "icq_querier_lib", - None, - "", - )?; - - info!("icq querier lib address: {}", icq_test_lib.address); - - info!("attempting GAMM total liquidity query"); - - let gamm_query_params = json!({ - "pool_id": "1" - }); - - println!("json gamm query: {:?}", gamm_query_params); - - // let kvq_registration_response = register_kvq( - // &test_ctx, - // icq_test_lib.address.to_string(), - // osmo_domain_registry.address.to_string(), - // osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), - // gamm_query_params.as_object().unwrap().clone(), - // )?; - - // info!( - // "kv query registration response: {:?}", - // kvq_registration_response - // ); - - // std::thread::sleep(Duration::from_secs(2)); - - // let bank_query_params = json!({ - // "addr": OSMOSIS_CHAIN_ADMIN_ADDR.to_string(), - // "denom": OSMOSIS_CHAIN_DENOM.to_string(), - // }); - - // println!("json bank query: {:?}", bank_query_params); - - // let kvq_registration_response = register_kvq( - // &test_ctx, - // icq_test_lib.address.to_string(), - // osmo_domain_registry.address.to_string(), - // osmosis_std::types::cosmos::bank::v1beta1::QueryBalanceResponse::TYPE_URL.to_string(), - // bank_query_params.as_object().unwrap().clone(), - // )?; - - // info!( - // "kv query registration response: {:?}", - // kvq_registration_response - // ); - - // let mut results_found = false; - // let mut results = vec![]; - // while !results_found { - // results = query_results(&test_ctx, icq_test_lib.address.to_string())?; - - // if results.len() == 2 { - // info!("results: {:?}", results); - // results_found = true; - // } else { - // info!("no results yet; sleeping for 3..."); - // std::thread::sleep(Duration::from_secs(3)); - // } - // } - - // let resp_1 = assert_icq_result( - // &test_ctx, - // icq_test_lib.address.to_string(), - // results[0].0, - // vec![ - // "/pool_assets/0/token/amount".to_string(), - // "/pool_assets/1/token/amount".to_string(), - // "==".to_string(), - // ], - // )?; - - // std::thread::sleep(Duration::from_secs(3)); - // info!("assertion #1 result: {:?}", resp_1); - - // let balance_amount: String = results[1] - // .1 - // .pointer("/coins/0/amount") - // .unwrap() - // .as_str() - // .unwrap() - // .to_string(); - // info!("passing balance for assertion: {balance_amount}"); - // let resp_2 = assert_icq_result( - // &test_ctx, - // icq_test_lib.address.to_string(), - // results[1].0, - // vec![ - // "/coins/0/amount".to_string(), - // balance_amount, // passing true - // "==".to_string(), - // ], - // )?; - // std::thread::sleep(Duration::from_secs(3)); - - // info!("assertion #2 result: {:?}", resp_2); - - // let resp_3 = assert_icq_result( - // &test_ctx, - // icq_test_lib.address.to_string(), - // results[1].0, - // vec![ - // "/coins/0/amount".to_string(), - // "314".to_string(), // passing false assertion value - // "==".to_string(), - // ], - // )?; - // std::thread::sleep(Duration::from_secs(3)); - - // info!("assertion #3 result: {:?}", resp_3); - - Ok(()) -} - -// pub fn assert_icq_result( -// test_ctx: &TestContext, -// icq_lib: String, -// query_id: u64, -// assertion: Vec, -// ) -> Result { -// let icq_assertion_msg = FunctionMsgs::AssertQueryResult { -// query_id, -// assertion, -// }; - -// let stringified_msg = serde_json::to_string(&icq_assertion_msg) -// .map_err(|e| LocalError::Custom { msg: e.to_string() })?; - -// info!("asserting query {query_id} result: {stringified_msg}"); - -// contract_execute( -// test_ctx -// .get_request_builder() -// .get_request_builder(NEUTRON_CHAIN_NAME), -// &icq_lib, -// DEFAULT_KEY, -// &stringified_msg, -// "--amount 1000000untrn --gas 50000000", -// ) -// } - -// pub fn register_kvq( -// test_ctx: &TestContext, -// icq_lib: String, -// type_registry: String, -// module: String, -// query: serde_json::Map, -// ) -> Result { -// let register_kvq_msg = FunctionMsgs::RegisterKvQuery { -// type_registry, -// module, -// query, -// }; - -// let stringified_msg = serde_json::to_string(®ister_kvq_msg) -// .map_err(|e| LocalError::Custom { msg: e.to_string() })?; - -// info!( -// "registering ICQ KV query on querier {icq_lib} : {:?}", -// stringified_msg -// ); - -// contract_execute( -// test_ctx -// .get_request_builder() -// .get_request_builder(NEUTRON_CHAIN_NAME), -// &icq_lib, -// DEFAULT_KEY, -// &stringified_msg, -// "--amount 1000000untrn --gas 50000000", -// ) -// } - -pub fn query_results( - test_ctx: &TestContext, - icq_lib: String, -) -> Result, LocalError> { - let query_response = contract_query( - test_ctx - .get_request_builder() - .get_request_builder(NEUTRON_CHAIN_NAME), - &icq_lib, - &serde_json::to_string(&QueryMsg::QueryResults {}) - .map_err(|e| LocalError::Custom { msg: e.to_string() })?, - )["data"] - .clone(); - - let resp: Vec<(u64, Value)> = serde_json::from_value(query_response).unwrap(); - - Ok(resp) -} From 5eec62c8da04ac71299498d29ce9c67997321e3f Mon Sep 17 00:00:00 2001 From: bekauz Date: Fri, 20 Dec 2024 16:13:12 +0100 Subject: [PATCH 92/92] remove icq-querier-utils; cleanup --- Cargo.lock | 25 --- Cargo.toml | 1 - contracts/libraries/icq-querier/Cargo.toml | 1 - .../libraries/icq-querier/src/contract.rs | 27 ++- contracts/libraries/icq-querier/src/msg.rs | 1 + contracts/libraries/icq-querier/src/state.rs | 9 +- contracts/middleware/broker/src/contract.rs | 8 +- .../middleware/broker/src/testing/mod.rs | 8 +- local-interchaintest/Cargo.toml | 1 - .../examples/middleware_icq_test.rs | 30 +-- packages/icq-querier-utils/Cargo.toml | 38 ---- packages/icq-querier-utils/src/lib.rs | 175 ------------------ .../src/type_registry/macros.rs | 6 +- .../src/type_registry/types.rs | 6 +- 14 files changed, 50 insertions(+), 286 deletions(-) delete mode 100644 packages/icq-querier-utils/Cargo.toml delete mode 100644 packages/icq-querier-utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index fd6d9a2b..914c3c41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2568,7 +2568,6 @@ dependencies = [ "valence-forwarder-library", "valence-generic-ibc-transfer-library", "valence-ibc-utils", - "valence-icq-lib-utils", "valence-icq-querier", "valence-library-utils", "valence-middleware-broker", @@ -5217,29 +5216,6 @@ dependencies = [ "serde", ] -[[package]] -name = "valence-icq-lib-utils" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema 2.1.4", - "cosmwasm-std 2.1.4", - "cw-denom", - "cw-multi-test", - "cw-ownable", - "cw-storage-plus 2.0.0", - "cw-utils 2.0.0", - "cw20 2.0.0", - "cw20-base", - "neutron-sdk", - "serde", - "serde_json", - "sha2 0.10.8", - "thiserror 1.0.69", - "valence-account-utils", - "valence-base-account", - "valence-macros", -] - [[package]] name = "valence-icq-querier" version = "0.1.0" @@ -5252,7 +5228,6 @@ dependencies = [ "neutron-sdk", "serde-json-wasm 1.0.1", "thiserror 1.0.69", - "valence-icq-lib-utils", "valence-library-base", "valence-library-utils", "valence-macros", diff --git a/Cargo.toml b/Cargo.toml index 7b337845..5f1279bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,6 @@ valence-library-utils = { path = "packages/library-utils" } valence-program-registry-utils = { path = "packages/program-registry-utils" } valence-program-manager = { path = "program-manager" } valence-program-registry = { path = "contracts/program-registry", features = ["library"] } -valence-icq-lib-utils = { path = "packages/icq-querier-utils" } valence-middleware-utils = { path = "packages/middleware-utils" } # dev-dependencies diff --git a/contracts/libraries/icq-querier/Cargo.toml b/contracts/libraries/icq-querier/Cargo.toml index 1ae51823..e203ac31 100644 --- a/contracts/libraries/icq-querier/Cargo.toml +++ b/contracts/libraries/icq-querier/Cargo.toml @@ -24,7 +24,6 @@ neutron-sdk = { workspace = true } serde-json-wasm = { version = "1.0.0", default-features = false } cw-storage-plus = { workspace = true } thiserror = { workspace = true } -valence-icq-lib-utils = { workspace = true } valence-middleware-broker = { workspace = true } valence-middleware-utils = { workspace = true } diff --git a/contracts/libraries/icq-querier/src/contract.rs b/contracts/libraries/icq-querier/src/contract.rs index 666e3ce0..1a6f14f9 100644 --- a/contracts/libraries/icq-querier/src/contract.rs +++ b/contracts/libraries/icq-querier/src/contract.rs @@ -15,14 +15,13 @@ use neutron_sdk::{ interchain_queries::{queries::get_raw_interchain_query_result, types::QueryType}, sudo::msg::SudoMsg, }; -use valence_icq_lib_utils::PendingQueryIdConfig; use valence_library_utils::error::LibraryError; use valence_middleware_utils::type_registry::types::{NativeTypeWrapper, RegistryQueryMsg}; use crate::{ msg::{Config, FunctionMsgs, InstantiateMsg, LibraryConfig, QueryMsg}, - state::{ASSOCIATED_QUERY_IDS, QUERY_RESULTS}, + state::{PendingQueryIdConfig, ASSOCIATED_QUERY_IDS, QUERY_RESULTS}, }; // version info for migration info @@ -52,16 +51,25 @@ pub fn execute( match msg { FunctionMsgs::RegisterKvQuery { broker_addr, + registry_version, type_id, connection_id, params, - } => register_kv_query(deps, broker_addr, type_id, connection_id, params), + } => register_kv_query( + deps, + broker_addr, + registry_version, + type_id, + connection_id, + params, + ), } } fn register_kv_query( deps: DepsMut, broker_addr: String, + registry_version: Option, type_id: String, connection_id: String, params: BTreeMap, @@ -69,7 +77,7 @@ fn register_kv_query( let query_kv_key: KVKey = deps.querier.query_wasm_smart( broker_addr.to_string(), &valence_middleware_broker::msg::QueryMsg { - registry_version: None, + registry_version: registry_version.clone(), query: RegistryQueryMsg::KVKey { type_id: type_id.to_string(), params, @@ -91,8 +99,9 @@ fn register_kv_query( deps.storage, 1, &PendingQueryIdConfig { - associated_domain_registry: broker_addr, - query_type: type_id, + broker_addr, + type_url: type_id, + registry_version, }, )?; @@ -155,11 +164,11 @@ fn handle_sudo_kv_query_result( let pending_query_config = ASSOCIATED_QUERY_IDS.load(deps.storage, query_id)?; let reconstruction_response: NativeTypeWrapper = deps.querier.query_wasm_smart( - pending_query_config.associated_domain_registry, + pending_query_config.broker_addr, &valence_middleware_broker::msg::QueryMsg { - registry_version: None, + registry_version: pending_query_config.registry_version, query: RegistryQueryMsg::ReconstructProto { - query_id: pending_query_config.query_type, + type_id: pending_query_config.type_url, icq_result: registered_query_result.result, }, }, diff --git a/contracts/libraries/icq-querier/src/msg.rs b/contracts/libraries/icq-querier/src/msg.rs index c352d1ec..309a6e91 100644 --- a/contracts/libraries/icq-querier/src/msg.rs +++ b/contracts/libraries/icq-querier/src/msg.rs @@ -15,6 +15,7 @@ pub struct InstantiateMsg {} pub enum FunctionMsgs { RegisterKvQuery { broker_addr: String, + registry_version: Option, type_id: String, connection_id: String, params: BTreeMap, diff --git a/contracts/libraries/icq-querier/src/state.rs b/contracts/libraries/icq-querier/src/state.rs index 6d047433..600cf4c4 100644 --- a/contracts/libraries/icq-querier/src/state.rs +++ b/contracts/libraries/icq-querier/src/state.rs @@ -1,6 +1,13 @@ +use cosmwasm_schema::cw_serde; use cosmwasm_std::Binary; use cw_storage_plus::Map; -use valence_icq_lib_utils::PendingQueryIdConfig; pub const ASSOCIATED_QUERY_IDS: Map = Map::new("associated_query_ids"); pub const QUERY_RESULTS: Map = Map::new("query_results"); + +#[cw_serde] +pub struct PendingQueryIdConfig { + pub type_url: String, + pub broker_addr: String, + pub registry_version: Option, +} diff --git a/contracts/middleware/broker/src/contract.rs b/contracts/middleware/broker/src/contract.rs index d0e14655..1861c8a3 100644 --- a/contracts/middleware/broker/src/contract.rs +++ b/contracts/middleware/broker/src/contract.rs @@ -77,12 +77,12 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg.query { RegistryQueryMsg::ReconstructProto { - query_id, + type_id, icq_result, } => try_decode_proto( deps, registry.registry_address.to_string(), - query_id, + type_id, icq_result, ), RegistryQueryMsg::KVKey { type_id, params } => { @@ -103,13 +103,13 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { fn try_decode_proto( deps: Deps, registry: String, - query_id: String, + type_id: String, icq_result: InterchainQueryResult, ) -> StdResult { let resp: NativeTypeWrapper = deps.querier.query_wasm_smart( registry, &RegistryQueryMsg::ReconstructProto { - query_id, + type_id, icq_result, }, )?; diff --git a/contracts/middleware/broker/src/testing/mod.rs b/contracts/middleware/broker/src/testing/mod.rs index 1e5ace77..69cb0c6b 100644 --- a/contracts/middleware/broker/src/testing/mod.rs +++ b/contracts/middleware/broker/src/testing/mod.rs @@ -87,13 +87,13 @@ impl Suite { fn query_decode_proto( &mut self, - query_id: &str, + type_id: &str, icq_result: InterchainQueryResult, ) -> StdResult { let msg = QueryMsg { registry_version: None, query: RegistryQueryMsg::ReconstructProto { - query_id: query_id.to_string(), + type_id: type_id.to_string(), icq_result, }, }; @@ -102,11 +102,11 @@ impl Suite { .query_wasm_smart(self.broker_addr.clone(), &msg) } - fn get_kv_key(&mut self, query_id: &str, params: BTreeMap) -> StdResult { + fn get_kv_key(&mut self, type_id: &str, params: BTreeMap) -> StdResult { let msg = QueryMsg { registry_version: None, query: RegistryQueryMsg::KVKey { - type_id: query_id.to_string(), + type_id: type_id.to_string(), params, }, }; diff --git a/local-interchaintest/Cargo.toml b/local-interchaintest/Cargo.toml index 8a45d942..9f81bae1 100644 --- a/local-interchaintest/Cargo.toml +++ b/local-interchaintest/Cargo.toml @@ -48,7 +48,6 @@ osmosis-std = { workspace = true } valence-test-icq-lib = { workspace = true } neutron-sdk = { workspace = true } valence-icq-querier = { workspace = true } -valence-icq-lib-utils = { workspace = true } valence-middleware-broker = { workspace = true } valence-middleware-osmosis = { workspace = true } valence-middleware-utils = { workspace = true } diff --git a/local-interchaintest/examples/middleware_icq_test.rs b/local-interchaintest/examples/middleware_icq_test.rs index 248ba216..49c55f0c 100644 --- a/local-interchaintest/examples/middleware_icq_test.rs +++ b/local-interchaintest/examples/middleware_icq_test.rs @@ -73,21 +73,18 @@ fn main() -> Result<(), Box> { current_dir.display() ); - info!("sleeping for 5 to allow icq relayer to start..."); + info!("sleeping for 10 to allow icq relayer to start..."); std::thread::sleep(Duration::from_secs(10)); uploader .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&icq_lib_local_path)?; - std::thread::sleep(Duration::from_secs(1)); uploader .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&osmosis_type_registry_middleware_path)?; - std::thread::sleep(Duration::from_secs(1)); uploader .with_chain_name(NEUTRON_CHAIN_NAME) .send_single_contract(&osmosis_middleware_broker_path)?; - std::thread::sleep(Duration::from_secs(1)); // set up the ICQ querier let icq_querier_lib_code_id = test_ctx @@ -158,42 +155,30 @@ fn main() -> Result<(), Box> { std::thread::sleep(Duration::from_secs(3)); // associate type registry with broker - let set_registry_response = set_type_registry( + set_type_registry( &test_ctx, broker_contract.address.to_string(), type_registry_contract.address, "26.0.0".to_string(), )?; - - info!( - "type registry addition response: {:?}", - set_registry_response - ); std::thread::sleep(Duration::from_secs(2)); - let gamm_query_params = - BTreeMap::from([("pool_id".to_string(), to_json_binary(&pool_id).unwrap())]); - let ntrn_to_osmo_connection_id = test_ctx .get_connections() .src(NEUTRON_CHAIN_NAME) .dest(OSMOSIS_CHAIN_NAME) .get(); - let kvq_registration_response = register_kvq( + // fire the query registration request + register_kvq( &test_ctx, icq_test_lib.address.to_string(), broker_contract.address.to_string(), osmosis_std::types::osmosis::gamm::v1beta1::Pool::TYPE_URL.to_string(), ntrn_to_osmo_connection_id, - gamm_query_params, + BTreeMap::from([("pool_id".to_string(), to_json_binary(&pool_id).unwrap())]), )?; - info!( - "KEY VALUE QUERY REGISTRATION RESPONSE TXHASH: {}", - kvq_registration_response.tx_hash.unwrap() - ); - std::thread::sleep(Duration::from_secs(10)); info!("querying results..."); @@ -258,6 +243,7 @@ pub fn register_kvq( params: BTreeMap, ) -> Result { let register_kvq_msg = FunctionMsgs::RegisterKvQuery { + registry_version: None, broker_addr, type_id, connection_id, @@ -297,7 +283,7 @@ pub fn query_results( )["data"] .clone(); - println!("query response: {:?}", query_response); + info!("query response: {:?}", query_response); let resp: Vec<(u64, Binary)> = serde_json::from_value(query_response).unwrap(); Ok(resp) @@ -322,7 +308,7 @@ pub fn broker_get_canonical( )["data"] .clone(); - println!("query response: {:?}", query_response); + info!("query response: {:?}", query_response); let resp: ValenceType = serde_json::from_value(query_response).unwrap(); Ok(resp) diff --git a/packages/icq-querier-utils/Cargo.toml b/packages/icq-querier-utils/Cargo.toml deleted file mode 100644 index 27877fb6..00000000 --- a/packages/icq-querier-utils/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "valence-icq-lib-utils" -authors = { workspace = true } -edition = { workspace = true } -license = { workspace = true } -version = { workspace = true } -repository = { workspace = true } - -[features] -default = [] -testing = [ - "dep:cw-multi-test", - "dep:cw20", - "dep:cw20-base", - "dep:sha2", - "dep:valence-base-account", -] - -[dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw-denom = { workspace = true } -cw-ownable = { workspace = true } -cw-utils = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -thiserror = { workspace = true } -valence-account-utils = { workspace = true } -valence-macros = { workspace = true } -cw-storage-plus = { workspace = true } -neutron-sdk = { workspace = true } - -# Testing dependencies -cw-multi-test = { workspace = true, optional = true } -cw20 = { workspace = true, optional = true } -cw20-base = { workspace = true, optional = true } -sha2 = { workspace = true, optional = true } -valence-base-account = { workspace = true, optional = true } diff --git a/packages/icq-querier-utils/src/lib.rs b/packages/icq-querier-utils/src/lib.rs deleted file mode 100644 index 96d96361..00000000 --- a/packages/icq-querier-utils/src/lib.rs +++ /dev/null @@ -1,175 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{StdError, StdResult}; -use neutron_sdk::bindings::{msg::NeutronMsg, types::InterchainQueryResult}; -use serde_json::Value; - -#[cw_serde] -pub struct InstantiateMsg { - // connection id of associated chain - pub connection_id: String, -} - -#[cw_serde] -pub enum ExecuteMsg {} - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(QueryRegistrationInfoResponse)] - GetRegistrationConfig(QueryRegistrationInfoRequest), - - #[returns(QueryReconstructionResponse)] - ReconstructQuery(QueryReconstructionRequest), -} - -#[cw_serde] -pub struct QueryReconstructionRequest { - pub icq_result: InterchainQueryResult, - pub query_type: String, -} - -#[cw_serde] -pub struct QueryReconstructionResponse { - pub json_value: Value, -} - -#[cw_serde] -pub struct QueryRegistrationInfoRequest { - /// module here refers to some string identifier of the query we want to perform. - /// one useful identifier is that of the proto type, e.g. `/osmosis.gamm.v1beta1.Pool`. - /// basically describes what type we are dealing with - pub module: String, - /// params here describe the parameters to be passed into our query request. - /// if module above describes the what, these params describe the how. - pub params: serde_json::Map, -} - -#[cw_serde] -pub struct QueryRegistrationInfoResponse { - pub registration_msg: NeutronMsg, - pub reply_id: u64, -} - -#[cw_serde] -pub struct PendingQueryIdConfig { - pub associated_domain_registry: String, - pub query_type: String, -} - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum TypeRegistryError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("Unknown reply id: {0}")] - UnknownReplyId(u64), - - #[error("Unsupported module: {0}")] - UnsupportedModule(String), - - #[error("Unknown type URL: {0}")] - UnknownTypeUrl(String), - - #[error("json field {0} missing from the query params: {1:?}")] - JsonFieldMissing(String, serde_json::Map), -} - -impl From for StdError { - fn from(val: TypeRegistryError) -> Self { - match val { - TypeRegistryError::Std(std_error) => std_error, - e => StdError::generic_err(e.to_string()), - } - } -} - -/// macro to generate enums for types we wish to support in each domain -/// registry -#[macro_export] -macro_rules! define_registry_types { - ($(($variant:ident, $type:ty)),* $(,)?) => { - #[allow(clippy::large_enum_variant)] - #[cw_serde] - pub enum DomainRegistryType { - $( - $variant($type), - )* - } - - /// default implementation for a str parser to go from proto type url to - /// the actual type - impl FromStr for DomainRegistryType - where $($type: QueryTypeDefinition, )* - { - type Err = $crate::TypeRegistryError; - - fn from_str(type_url: &str) -> Result { - match type_url { - $( - <$type>::TYPE_URL => Ok(DomainRegistryType::$variant(<$type>::default())), - )* - _ => Err($crate::TypeRegistryError::UnknownTypeUrl(type_url.to_string())), - } - } - } - - impl DomainRegistryType { - pub fn get_registration_config(&self, params: serde_json::Map) -> StdResult<(KVKey, u64)> { - match self { - $( - DomainRegistryType::$variant(t) => Ok(( - t.get_kv_key(params)?, - <$type>::REPLY_ID, )), - )* - } - } - - pub fn reconstruct_response(&self, request: &QueryReconstructionRequest) -> StdResult { - match self { - $( - DomainRegistryType::$variant(_t) => <$type>::decode_and_reconstruct(request), - )* - } - } - } - - }; -} - -pub fn get_u64_query_param(params: &serde_json::Map, key: &str) -> StdResult { - let value = match params.get(key) { - Some(Value::Number(number)) => number.as_u64().ok_or(StdError::generic_err(format!( - "failed to parse {:?} as u64 for {key} access", - number - ))), - Some(Value::String(str_num)) => str_num.parse::().map_err(|_| { - StdError::generic_err(format!( - "failed to parse {:?} to u64 for key {key}", - str_num - )) - }), - _ => Err(StdError::generic_err(format!( - "field pool_id missing from query params: {:?}", - params - ))), - }?; - - Ok(value) -} - -pub fn get_str_query_param( - params: &serde_json::Map, - key: &str, -) -> StdResult { - let value = match params.get(key) { - Some(Value::String(str_val)) => Ok(str_val), - _ => Err(StdError::generic_err(format!( - "field {key} missing from query params: {:?}", - params - ))), - }?; - - Ok(value.to_string()) -} diff --git a/packages/middleware-utils/src/type_registry/macros.rs b/packages/middleware-utils/src/type_registry/macros.rs index 641468ef..a29bca4c 100644 --- a/packages/middleware-utils/src/type_registry/macros.rs +++ b/packages/middleware-utils/src/type_registry/macros.rs @@ -55,11 +55,11 @@ macro_rules! register_types { _ => Err(::cosmwasm_std::StdError::generic_err("unknown type")) } }, - RegistryQueryMsg::ReconstructProto { query_id, icq_result } => { - match query_id.as_str() { + RegistryQueryMsg::ReconstructProto { type_id, icq_result } => { + match type_id.as_str() { $( $type_id => { - let binary = <$adapter>::decode_and_reconstruct(query_id, icq_result) + let binary = <$adapter>::decode_and_reconstruct(type_id, icq_result) .map_err(|_| StdError::generic_err("failed to reconstruct type from proto"))?; to_json_binary(&NativeTypeWrapper { binary }) }, diff --git a/packages/middleware-utils/src/type_registry/types.rs b/packages/middleware-utils/src/type_registry/types.rs index 099ececa..26c9c33f 100644 --- a/packages/middleware-utils/src/type_registry/types.rs +++ b/packages/middleware-utils/src/type_registry/types.rs @@ -13,7 +13,9 @@ pub enum RegistryExecuteMsg {} /// this is effectively the valence vm types that are enabled /// on a system level. if a particular type is not defined here, -/// it cannot be used in programs. +/// it cannot be used in programs. if a type is here, then developers +/// are free to integrate any remote types that would fall into +/// any of these categories. #[cw_serde] pub enum ValenceType { XykPool(ValenceXykPool), @@ -39,7 +41,7 @@ pub enum RegistryQueryMsg { #[returns(NativeTypeWrapper)] ReconstructProto { - query_id: String, + type_id: String, icq_result: InterchainQueryResult, }, // TODO: transform an outdated type to a new version