diff --git a/Cargo.lock b/Cargo.lock index d849109..7d06595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,12 +19,51 @@ version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +[[package]] +name = "astroport" +version = "4.0.0" +source = "git+https://github.com/astroport-fi/astroport-core#5bff86a0229c7bd96e9f719d0c5907b9b8c3762d" +dependencies = [ + "astroport-circular-buffer", + "cosmwasm-schema", + "cosmwasm-std", + "cw-asset", + "cw-storage-plus", + "cw-utils", + "cw20", + "itertools 0.12.1", + "uint", +] + +[[package]] +name = "astroport-circular-buffer" +version = "0.2.0" +source = "git+https://github.com/astroport-fi/astroport-core#5bff86a0229c7bd96e9f719d0c5907b9b8c3762d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "thiserror", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "balance-tracker" +version = "0.1.0" +dependencies = [ + "astroport", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "cw2", + "thiserror", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -233,6 +272,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -268,6 +313,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cw-address-like" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451a4691083a88a3c0630a8a88799e9d4cd6679b7ce8ff22b8da2873ff31d380" +dependencies = [ + "cosmwasm-std", +] + +[[package]] +name = "cw-asset" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c999a12f8cd8736f6f86e9a4ede5905530cb23cfdef946b9da1c506ad1b70799" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like", + "cw-storage-plus", + "cw20", + "thiserror", +] + [[package]] name = "cw-storage-plus" version = "1.2.0" @@ -279,6 +347,21 @@ dependencies = [ "serde", ] +[[package]] +name = "cw-utils" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2", + "schemars", + "semver", + "serde", + "thiserror", +] + [[package]] name = "cw2" version = "1.1.2" @@ -294,6 +377,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw20" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "526e39bb20534e25a1cd0386727f0038f4da294e5e535729ba3ef54055246abd" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils", + "schemars", + "serde", +] + [[package]] name = "der" version = "0.7.8" @@ -562,6 +658,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -1281,6 +1386,18 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/artifacts/checksums.txt b/artifacts/checksums.txt index fb2de7c..e1cbbeb 100644 --- a/artifacts/checksums.txt +++ b/artifacts/checksums.txt @@ -1,14 +1,15 @@ -cf31690dfd2478f42f55cea30fa3a9874f06cd328f736df3fdf687b5387e44fa before_send_hook_test-x86_64.wasm -d5e983d67abaac10be8b2e63391af00a2cae828f4b095e3f86b1330d2304c44b client_updater-x86_64.wasm -3b290fbf64137be653ff1452ec3a101f360f10cff521b569c3fcc54a1455a46e dex-x86_64.wasm -e85798953e4b1ddd5561ab75c8330646043259bd5eb5cdadee6214e05f37ac2a dex_stargate-x86_64.wasm -45f13bb2a934f5c95c634dd12da9d95d0aeef498c08b81c0de1009fb90d65306 echo-x86_64.wasm -ef21b5544bd40a188198c6e2c88477c8d223562e7ded42e3773e3c62b07154ac ibc_transfer-x86_64.wasm -6ebaf70045ce390df28db83a65be6a1dfac46626d7242268d7d95f82c70d2855 msg_receiver-x86_64.wasm -0e59719cf88bc458011630af1b6b724f1e3c74eb440e92a117d1525088d4793f neutron_price_feed_mock-x86_64.wasm -11cee5c2a11bff1a0e41a0f3cfe3061adb909670bb29dd45daed9831ba34c133 neutron_interchain_queries-x86_64.wasm -5442356c8780004821e4690eb8547b4fdbcd9134ad4eb94cc5e9e2decb65fd82 neutron_interchain_txs-x86_64.wasm -b2f6dde6d73b39d6d9ab778632af600e172ecf44dc02159095325e92e18663ae neutron_validators_test-x86_64.wasm -4884f1ce16c7fd854d4e9900dc5ff6c67c7b18588eab6de4a162a116f7735af7 reflect-x86_64.wasm -c4c6e59c08048d5c1275d2a35a84a5b91862b827012704415ed5aa56363a362e stargate_querier-x86_64.wasm -d146050aca63e1a52932675a67dfd4aa9a23948383fbad275cc7ffb0ef1b2145 tokenfactory-x86_64.wasm +0c52b85da277055d45075144d7566d40490519486e93601793e7f298e0b80a99 balance_tracker.wasm +9fc5cc70b25d3faa19199bb83b148274794d7df96e4a16f60a53781410b11da2 before_send_hook_test.wasm +0e145a43d5bce9e04ae8db21f2dcc5c897fa7ae65c3cdbcfc846e3e34b2dd793 client_updater.wasm +8f514402615c949263062772b3481a4919777577ff3841128949e53561d0cc61 dex.wasm +4ebb637e1085f24a7a8a023c7955020fc6db340248361d7f7b2b16c17691d7ea dex_stargate.wasm +cbaf8c3e0f063ed8f5fb8be6dc846196cba26455c8d2b1e4cf60ddce06e68d94 echo.wasm +8d05f93af63df857f0e69c1023b3c1fbbfabc0459a6a4249367588874f795030 ibc_transfer.wasm +ebe171cfafe79343f84e0f49e412fec174ddc8a0753d7ec9749bd81e0bf17f55 msg_receiver.wasm +3efca7bfbab65ff18fdf3ac12626939b2a605a6717eeef404d0eec25c864df57 neutron_interchain_queries.wasm +53508475d18898aaac829a55fa38b8fe31870583ede740d6b175a025ccecd6d1 neutron_interchain_txs.wasm +da2a1e14f3658c69846f7f9773c9eb39bc4dd243946bd22ca47079b314b3ebbb neutron_price_feed_mock.wasm +8b7e9946dc8c86729fdecbebd51fd8eeb360da48c1ce5cb9be52319584c376f9 neutron_validators_test.wasm +14d4dce209e210f20bce9fb835194a1d53fe1a99a5ee78f916e51d41d0679bf6 reflect.wasm +3a720c4ee3de2f9d1bb66d20582f14168084c40c00d8a9240d2c6a26750894c8 stargate_querier.wasm +f49da4ab5ee960686c942408a348cd9125fa6d1b93ad328a6e938374e6e0df7d tokenfactory.wasm diff --git a/artifacts/checksums_intermediate.txt b/artifacts/checksums_intermediate.txt deleted file mode 100644 index d2c3d6b..0000000 --- a/artifacts/checksums_intermediate.txt +++ /dev/null @@ -1,14 +0,0 @@ -732392426c1160ea1899955ee7ea263db5d5023fd601115c2039dfa9df648738 before_send_hook_test.wasm -52b18e18dd1782d46e425acfc82d0a88de5153834fbeec5e9db83703e2e05153 client_updater.wasm -01ab3c76b0f34dba1f52d8bb3a827deed26b295138f9ee01733842f408d1b909 dex.wasm -ca2ec2b77a90c2b2a76fb9cc59256e571ffe76ae3c9f6ee72838715153e89fd2 dex_stargate.wasm -212e7034418b28abacbf393438f0c509cbad294be51153a38a8288c95b67a67a echo.wasm -bfa8799864fba19455f1a11301d4312e22c17bd4019826e8ba5f9dd4e9a456d3 ibc_transfer.wasm -42ac2bd34a8a4e7c9db0a28592354e9eb000d5c0d644e160b9064f20d8873240 msg_receiver.wasm -4d2ec7085a1dd6e8a4eab15a15580b7343ddde273c1a6471622c632573361343 neutron_price_feed_mock.wasm -a35efe4e5ddcbddccfcf0e13385cd7aa9b95da642a67441bb9b1301041bd8ea2 neutron_interchain_queries.wasm -8763335f18eff836ee0797ada8d5362eaddcd72ee2cafaebe71dfef7d4595aed neutron_interchain_txs.wasm -4aa23ebc76c3fe48c451b19b4a8076476ead1dd74dc964ca67b30efb09857e72 neutron_validators_test.wasm -d4c10fb536cb64ca91be931efa24682e85e6ff3c0a58d440390a9e820bd0d049 reflect.wasm -a782e7867ec0dddac3d7684f5e9e106dbff475ff1cf9c355626acc8cf9018928 stargate_querier.wasm -dbdde027d2071120270f1f53bd87fdd7eff844b34b98facbcd8c7172e4c7d502 tokenfactory.wasm diff --git a/contracts/balance-tracker/.cargo/config b/contracts/balance-tracker/.cargo/config new file mode 100644 index 0000000..52fc65f --- /dev/null +++ b/contracts/balance-tracker/.cargo/config @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --example tokenfactory_tracker_schema" diff --git a/contracts/balance-tracker/Cargo.toml b/contracts/balance-tracker/Cargo.toml new file mode 100644 index 0000000..1297d80 --- /dev/null +++ b/contracts/balance-tracker/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "balance-tracker" +version = "0.1.0" +edition = "2021" + +[features] +library = [] + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +opt-level = "z" +debug = false +rpath = false +lto = true +debug-assertions = false +codegen-units = 1 +panic = 'abort' +incremental = false +overflow-checks = true +strip = true + +[dependencies] +cw2 = "1" +cosmwasm-std = "1.5" +cw-storage-plus = "1.2" +cosmwasm-schema = "1.5" +thiserror = "1" +astroport = { git = "https://github.com/astroport-fi/astroport-core", version = "4" } diff --git a/contracts/balance-tracker/README.md b/contracts/balance-tracker/README.md new file mode 100644 index 0000000..7efae75 --- /dev/null +++ b/contracts/balance-tracker/README.md @@ -0,0 +1,3 @@ +# Balance tracker + +A simple contract that tracks total supply and balance of tokens using TokenFactory bank hooks. \ No newline at end of file diff --git a/contracts/balance-tracker/src/contract.rs b/contracts/balance-tracker/src/contract.rs new file mode 100644 index 0000000..d8a7bc0 --- /dev/null +++ b/contracts/balance-tracker/src/contract.rs @@ -0,0 +1,141 @@ +use astroport::asset::validate_native_denom; +use astroport::tokenfactory_tracker::{InstantiateMsg, SudoMsg}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{DepsMut, Env, MessageInfo, Response, StdError, Storage, Uint128}; +use cw2::set_contract_version; + +use crate::error::ContractError; +use crate::state::{Config, BALANCES, CONFIG, TOTAL_SUPPLY_HISTORY}; + +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 { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + deps.api.addr_validate(&msg.tokenfactory_module_address)?; + + validate_native_denom(&msg.tracked_denom)?; + + let config = Config { + d: msg.tracked_denom.clone(), + m: msg.tokenfactory_module_address, + }; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::default() + .add_attribute("action", "instantiate") + .add_attribute("contract", CONTRACT_NAME) + .add_attribute("tracked_denom", config.d) + .add_attribute("tokenfactory_module_address", config.m)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { + match msg { + // BlockBeforeSend is called before a send - if an error is returned the send is cancelled. + // This call doesn't have gas limitations but the gas used due to calling this contract contributes to the total tx gas. + // Extended bank module calls BlockBeforeSend and TrackBeforeSend sequentially on mint, send and burn actions. + // Ref: https://github.com/neutron-org/cosmos-sdk/blob/28f3db48a7ae038e9ccdd2bae632cb21c1c9de86/x/bank/keeper/send.go#L207-L223 + SudoMsg::BlockBeforeSend { from, to, amount } => { + let config = CONFIG.load(deps.storage)?; + + // Ensure the denom being sent is the tracked denom + // If this isn't checked, another token could be tracked with the same + // contract and that will skew the real numbers + if amount.denom != config.d { + Err(ContractError::InvalidDenom { + expected_denom: config.d, + }) + } else { + // If this function throws error all send, mint and burn actions will be blocked. + // However, balances query will still work, hence governance will be able to recover the contract. + track_balances( + deps.storage, + env.block.time.seconds(), + &config, + from, + to, + amount.amount, + ) + } + } + // tokenfactory enforces hard gas limit 100k on TrackBeforeSend of which 60k is a flat contract initialization. + // Hence, we have only up to 40k gas to handle our logic. If TrackBeforeSend hits the limit it is silently ignored on chain level, + // making balance tracking broken with no way to recover. + // Balance tracking feature is crucial for Astroport and Neutron DAOs thus we deliberately abuse SudoMsg::BlockBeforeSend + // because it is not gas metered and we can do all the logic we need. + // Ref: https://github.com/neutron-org/neutron/blob/57a25eb719eb0db973543f9d54ace484ac098721/x/tokenfactory/keeper/before_send.go#L143-L150 + SudoMsg::TrackBeforeSend { .. } => Ok(Response::default()), + } +} + +/// Track balance and total supply changes over timestamp. +/// Only tokenfactory module itself can change supply by minting and burning tokens. +/// Only denom admin can dispatch mint/burn messages to the module. +/// Sending tokens to the tokenfactory module address isn't allowed by the chain. +/// Thus, +/// - if from == module_address -> mint +/// - if to == module_address -> burn +/// - other scenarios are simple transfers between addresses +/// Possible errors: +/// - serialization/deserialization errors. Should never happen if both BALANCES and TOTAL_SUPPLY_HISTORY storage keys and data layout are not changed. +/// - attempt to subtract from zero balance or reduce empty total supply. Highly unlikely possible. Might happen due to errors in the tokenfactory module. +/// - attempt to add with overflow. First will happen on total supply increase. Possible if total supply is greater than 2^128 - 1. +pub fn track_balances( + storage: &mut dyn Storage, + block_seconds: u64, + config: &Config, + from: String, + to: String, + amount: Uint128, +) -> Result { + // If the token is minted directly to an address, we don't need to subtract + // as the sender is the module address + if from.ne(&config.m) { + BALANCES.update::<_, StdError>(storage, &from, block_seconds, |balance| { + balance + .unwrap_or_default() + .checked_sub(amount) + .map_err(|err| { + StdError::generic_err(format!( + "{err}: send from {from} to {to} amount {amount} block_seconds {block_seconds}" + )) + }) + })?; + } else { + // Minted new tokens + TOTAL_SUPPLY_HISTORY.update::<_, StdError>(storage, block_seconds, |balance| { + Ok(balance.unwrap_or_default().checked_add(amount)?) + })?; + } + + // When burning tokens, the receiver is the token factory module address + // Sending tokens to the module address isn't allowed by the chain + if to.ne(&config.m) { + BALANCES.update::<_, StdError>(storage, &to, block_seconds, |balance| { + Ok(balance.unwrap_or_default().checked_add(amount)?) + })?; + } else { + // Burned tokens + TOTAL_SUPPLY_HISTORY.update::<_, StdError>(storage, block_seconds, |balance| { + balance + .unwrap_or_default() + .checked_sub(amount) + .map_err(|err| { + StdError::generic_err(format!( + "{err}: from {from} to {to} amount {amount} block_seconds {block_seconds}" + )) + }) + })?; + } + + Ok(Response::default()) +} diff --git a/contracts/balance-tracker/src/error.rs b/contracts/balance-tracker/src/error.rs new file mode 100644 index 0000000..f207b03 --- /dev/null +++ b/contracts/balance-tracker/src/error.rs @@ -0,0 +1,11 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Invalid denom, expected {expected_denom}")] + InvalidDenom { expected_denom: String }, +} diff --git a/contracts/balance-tracker/src/lib.rs b/contracts/balance-tracker/src/lib.rs new file mode 100644 index 0000000..326d472 --- /dev/null +++ b/contracts/balance-tracker/src/lib.rs @@ -0,0 +1,4 @@ +pub mod contract; +pub mod error; +pub mod query; +pub mod state; diff --git a/contracts/balance-tracker/src/query.rs b/contracts/balance-tracker/src/query.rs new file mode 100644 index 0000000..fba34a1 --- /dev/null +++ b/contracts/balance-tracker/src/query.rs @@ -0,0 +1,44 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_json_binary, Binary, Deps, Env, StdResult, Uint128}; + +use astroport::tokenfactory_tracker::{ConfigResponse, QueryMsg}; + +use crate::state::{BALANCES, CONFIG, TOTAL_SUPPLY_HISTORY}; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::BalanceAt { address, timestamp } => { + to_json_binary(&balance_at(deps, env, address, timestamp)?) + } + QueryMsg::TotalSupplyAt { timestamp } => { + to_json_binary(&total_supply_at(deps, env, timestamp)?) + } + QueryMsg::Config {} => { + let config = CONFIG.load(deps.storage)?; + to_json_binary(&ConfigResponse { + tracked_denom: config.d, + token_factory_module: config.m, + }) + } + } +} + +fn balance_at(deps: Deps, env: Env, address: String, timestamp: Option) -> StdResult { + let block_time = env.block.time.seconds(); + match timestamp.unwrap_or(block_time) { + timestamp if timestamp == block_time => BALANCES.may_load(deps.storage, &address), + timestamp => BALANCES.may_load_at_height(deps.storage, &address, timestamp), + } + .map(|balance| balance.unwrap_or_default()) +} + +fn total_supply_at(deps: Deps, env: Env, timestamp: Option) -> StdResult { + let block_time = env.block.time.seconds(); + match timestamp.unwrap_or(block_time) { + timestamp if timestamp == block_time => TOTAL_SUPPLY_HISTORY.may_load(deps.storage), + timestamp => TOTAL_SUPPLY_HISTORY.may_load_at_height(deps.storage, timestamp), + } + .map(|total_supply| total_supply.unwrap_or_default()) +} diff --git a/contracts/balance-tracker/src/state.rs b/contracts/balance-tracker/src/state.rs new file mode 100644 index 0000000..3d66b29 --- /dev/null +++ b/contracts/balance-tracker/src/state.rs @@ -0,0 +1,21 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::Uint128; +use cw_storage_plus::{Item, SnapshotItem, SnapshotMap, Strategy}; + +#[cw_serde] +pub struct Config { + /// Tracked denom + pub d: String, + /// Token factory module address + pub m: String, +} + +pub const CONFIG: Item = Item::new("c"); + +/// Contains snapshotted balances at every block. +pub const BALANCES: SnapshotMap<&str, Uint128> = + SnapshotMap::new("b", "b_chpts", "b_chlg", Strategy::EveryBlock); + +/// Contains the history of the total supply of the tracked denom +pub const TOTAL_SUPPLY_HISTORY: SnapshotItem = + SnapshotItem::new("t", "t_chpts", "t_chlg", Strategy::EveryBlock); diff --git a/contracts/dex/schema/dex_msg.json b/contracts/dex/schema/dex_msg.json index ac32f68..c731954 100644 --- a/contracts/dex/schema/dex_msg.json +++ b/contracts/dex/schema/dex_msg.json @@ -3,6 +3,7 @@ "title": "DexMsg", "oneOf": [ { + "description": "Deposit provides liquidity to a specific trading pair by depositing tokens at a specific price into one or both sides of the pair in “a liquidity pool”", "type": "object", "required": [ "deposit" @@ -22,18 +23,21 @@ ], "properties": { "amounts_a": { + "description": "Amounts of tokenA to deposit", "type": "array", "items": { "$ref": "#/definitions/Uint128" } }, "amounts_b": { + "description": "Amounts of tokenB to deposit", "type": "array", "items": { "$ref": "#/definitions/Uint128" } }, "fees": { + "description": "Fees to use for each deposit", "type": "array", "items": { "type": "integer", @@ -42,22 +46,18 @@ } }, "options": { + "description": "Additional deposit options", "type": "array", "items": { - "anyOf": [ - { - "$ref": "#/definitions/DepositOption" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/DepositOption" } }, "receiver": { + "description": "The account to which PoolShares will be issued", "type": "string" }, "tick_indexes_a_to_b": { + "description": "Tick indexes to deposit at defined in terms of TokenA to TokenB (ie. TokenA is on the left)", "type": "array", "items": { "type": "integer", @@ -65,9 +65,11 @@ } }, "token_a": { + "description": "Denom for one side of the deposit", "type": "string" }, "token_b": { + "description": "Denom for the opposing side of the deposit", "type": "string" } } @@ -76,6 +78,7 @@ "additionalProperties": false }, { + "description": "Withdraw is used to redeem PoolShares for the user’s pro-rata portion of tokens within a liquidity pool. Users can withdraw from a pool at any time", "type": "object", "required": [ "withdrawal" @@ -93,6 +96,7 @@ ], "properties": { "fees": { + "description": "Fee for the target LiquidityPools", "type": "array", "items": { "type": "integer", @@ -101,15 +105,18 @@ } }, "receiver": { + "description": "The account to which the tokens are credited", "type": "string" }, "shares_to_remove": { + "description": "Amount of shares to remove from each pool", "type": "array", "items": { "$ref": "#/definitions/Uint128" } }, "tick_indexes_a_to_b": { + "description": "Tick indexes of the target LiquidityPools defined in terms of TokenA to TokenB (ie. TokenA is on the left)", "type": "array", "items": { "type": "integer", @@ -117,9 +124,11 @@ } }, "token_a": { + "description": "Denom for one side of the deposit", "type": "string" }, "token_b": { + "description": "Denom for the opposing side of the deposit", "type": "string" } } @@ -128,6 +137,7 @@ "additionalProperties": false }, { + "description": "PlaceLimitOrder provides the primary mechanism for trading on the Duality Dex. Limit orders can provide liquidity to the Dex (“Maker Limit Orders”) and/or can be used to trade against preexisting liquidity (“Taker Limit Orders”)", "type": "object", "required": [ "place_limit_order" @@ -141,13 +151,19 @@ "receiver", "tick_index_in_to_out", "token_in", - "tonek_out" + "token_out" ], "properties": { "amount_in": { - "$ref": "#/definitions/Uint128" + "description": "Amount of TokenIn to be traded", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] }, "expiration_time": { + "description": "Expiration time for order. Only valid for GOOD_TIL_TIME limit orders", "type": [ "integer", "null" @@ -156,6 +172,7 @@ "minimum": 0.0 }, "max_amount_out": { + "description": "Maximum amount of TokenB can be bought. For everything except JUST_IN_TIME OrderType", "anyOf": [ { "$ref": "#/definitions/Uint128" @@ -166,19 +183,28 @@ ] }, "order_type": { - "$ref": "#/definitions/LimitOrderType" + "description": "Type of limit order to be used. Must be one of: GOOD_TIL_CANCELLED, FILL_OR_KILL, IMMEDIATE_OR_CANCEL, JUST_IN_TIME, or GOOD_TIL_TIME", + "allOf": [ + { + "$ref": "#/definitions/LimitOrderType" + } + ] }, "receiver": { + "description": "Account to which TokenOut is credited or that will be allowed to withdraw or cancel a maker order", "type": "string" }, "tick_index_in_to_out": { + "description": "Limit tick for a limit order, specified in terms of TokenIn to TokenOut", "type": "integer", "format": "int64" }, "token_in": { + "description": "Token being “sold”", "type": "string" }, - "tonek_out": { + "token_out": { + "description": "Token being “bought”", "type": "string" } } @@ -187,6 +213,7 @@ "additionalProperties": false }, { + "description": "WithdrawFilledLimitOrder. Once a limit order has been filled – either partially or in its entirety, it can be withdrawn at any time. Withdrawing from a limit order credits all available proceeds to the user. Withdraw can be called on a limit order multiple times as new proceeds become available", "type": "object", "required": [ "withdraw_filled_limit_order" @@ -199,6 +226,7 @@ ], "properties": { "tranche_key": { + "description": "TrancheKey for the target limit order", "type": "string" } } @@ -207,6 +235,7 @@ "additionalProperties": false }, { + "description": "CancelLimitOrder. Standard Taker limit orders (Good-til-cancelled & Good-til-Time) can be canceled at any time if they have not been completely filled", "type": "object", "required": [ "cancel_limit_order" @@ -219,6 +248,7 @@ ], "properties": { "tranche_key": { + "description": "TrancheKey for the target limit order", "type": "string" } } @@ -227,6 +257,7 @@ "additionalProperties": false }, { + "description": "MultiHopSwap provides a swapping mechanism to achieve better prices by routing through a series of pools", "type": "object", "required": [ "multi_hop_swap" @@ -243,28 +274,34 @@ ], "properties": { "amount_in": { - "$ref": "#/definitions/Uint128" + "description": "Amount of TokenIn to swap", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] }, "exit_limit_price": { - "$ref": "#/definitions/PrecDec" + "description": "Minimum price that that must be satisfied for a route to succeed", + "allOf": [ + { + "$ref": "#/definitions/PrecDec" + } + ] }, "pick_best_route": { + "description": "If true all routes are run and the route with the best price is used", "type": "boolean" }, "receiver": { + "description": "Account to which TokenOut is credited", "type": "string" }, "routes": { + "description": "Array of possible routes", "type": "array", "items": { - "anyOf": [ - { - "$ref": "#/definitions/MultiHopRoute" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/MultiHopRoute" } } } @@ -286,13 +323,42 @@ } }, "LimitOrderType": { - "type": "string", - "enum": [ - "GoodTillCancel", - "FillOrKill", - "ImmediateOrCancel", - "JustInTime", - "GoodTilTime" + "oneOf": [ + { + "description": "Good-til-Cancelled limit orders are hybrid maker and taker limit orders. They will attempt to trade the supplied AmountIn at the TickIndex or better. However, if they total AmountIn cannot be traded at the limit price they are remaining amount will be placed as a maker limit order. The proceeds from the taker portion are deposited into the user’s account immediately, however, the proceeds from the maker portion must be explicitly withdrawn via WithdrawLimitOrder.", + "type": "string", + "enum": [ + "GOOD_TIL_CANCELLED" + ] + }, + { + "description": "Fill-or-Kill limit orders are taker limit orders that either successfully swap 100% of the supplied AmountIn or return an error. If there is insufficient liquidity to complete the trade at or above the supplied TickIndex a Fill-or-Kill order will return an error `codespace: dex, code: 1134` (https://github.com/neutron-org/neutron/blob/main/x/dex/types/errors.go#L107 ErrGoodTilOrderWithoutExpiration).", + "type": "string", + "enum": [ + "FILL_OR_KILL" + ] + }, + { + "description": "Immediate-or-Cancel limit orders are taker orders that will swap as much as of the AmountIn as possible given available liquidity above the supplied TickIndex. Unlike Fill-or-Kill orders they will still successfully complete even if they are only able to partially trade through the AmountIn at the TickIndex or better.", + "type": "string", + "enum": [ + "IMMEDIATE_OR_CANCEL" + ] + }, + { + "description": "Just-in-Time limit orders are an advanced maker limit order that provides tradeable liquidity for exactly one block. At the end of the same block in which the Just-in-Time order was submitted the order is canceled and any untraded portion will no longer be usable as active liquidity.", + "type": "string", + "enum": [ + "JUST_IN_TIME" + ] + }, + { + "description": "Good-til-Time limit order function exactly the same as Good-til-Cancelled limit orders first trying to trade as a taker limit order and then placing any remaining amount as a maker limit order. However, the maker portion of the limit order has a specified ExpirationTime. After the ExpirationTime the order will be cancelled and can no longer be traded against. When withdrawing a Good-til-Time limit order the user will receive both the successfully traded portion of the limit order (TokenOut) as well as any remaining untraded amount (TokenIn).", + "type": "string", + "enum": [ + "GOOD_TIL_TIME" + ] + } ] }, "MultiHopRoute": { @@ -316,7 +382,7 @@ ], "properties": { "i": { - "$ref": "#/definitions/Uint128" + "type": "string" } } }, diff --git a/contracts/dex/schema/dex_query.json b/contracts/dex/schema/dex_query.json index b741119..61bd90c 100644 --- a/contracts/dex/schema/dex_query.json +++ b/contracts/dex/schema/dex_query.json @@ -3,6 +3,7 @@ "title": "DexQuery", "oneOf": [ { + "description": "Parameters queries the parameters of the module.", "type": "object", "required": [ "params" @@ -15,12 +16,13 @@ "additionalProperties": false }, { + "description": "Queries a LimitOrderTrancheUser by index.", "type": "object", "required": [ - "limit_order_trache_user" + "limit_order_tranche_user" ], "properties": { - "limit_order_trache_user": { + "limit_order_tranche_user": { "type": "object", "required": [ "address", @@ -39,6 +41,7 @@ "additionalProperties": false }, { + "description": "Queries a list of LimitOrderTrancheMap items.", "type": "object", "required": [ "limit_order_tranche_user_all" @@ -46,12 +49,16 @@ "properties": { "limit_order_tranche_user_all": { "type": "object", - "required": [ - "pagination" - ], "properties": { "pagination": { - "$ref": "#/definitions/PageRequest" + "anyOf": [ + { + "$ref": "#/definitions/PageRequest" + }, + { + "type": "null" + } + ] } } } @@ -59,6 +66,7 @@ "additionalProperties": false }, { + "description": "Queries a list of LimitOrderTrancheUser items for a given address.", "type": "object", "required": [ "limit_order_tranche_user_all_by_address" @@ -67,21 +75,11 @@ "limit_order_tranche_user_all_by_address": { "type": "object", "required": [ - "limit_orders" + "address" ], "properties": { - "limit_orders": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/LimitOrderTrancheUser" - }, - { - "type": "null" - } - ] - } + "address": { + "type": "string" }, "pagination": { "anyOf": [ @@ -99,6 +97,7 @@ "additionalProperties": false }, { + "description": "Queries a LimitOrderTranche by index.", "type": "object", "required": [ "limit_order_tranche" @@ -132,6 +131,7 @@ "additionalProperties": false }, { + "description": "Queries a list of LimitOrderTranche items for a given pairID / TokenIn combination.", "type": "object", "required": [ "limit_order_tranche_all" @@ -166,6 +166,7 @@ "additionalProperties": false }, { + "description": "Queries a list of UserDeposits items.", "type": "object", "required": [ "user_deposit_all" @@ -174,12 +175,16 @@ "user_deposit_all": { "type": "object", "required": [ - "address" + "address", + "include_pool_data" ], "properties": { "address": { "type": "string" }, + "include_pool_data": { + "type": "boolean" + }, "pagination": { "anyOf": [ { @@ -196,6 +201,7 @@ "additionalProperties": false }, { + "description": "Queries a list of TickLiquidity items.", "type": "object", "required": [ "tick_liquidity_all" @@ -230,6 +236,7 @@ "additionalProperties": false }, { + "description": "Queries a InactiveLimitOrderTranche by index.", "type": "object", "required": [ "inactive_limit_order_tranche" @@ -263,6 +270,7 @@ "additionalProperties": false }, { + "description": "Queries a list of InactiveLimitOrderTranche items.", "type": "object", "required": [ "inactive_limit_order_tranche_all" @@ -287,6 +295,7 @@ "additionalProperties": false }, { + "description": "Queries a list of PoolReserves items.", "type": "object", "required": [ "pool_reserves_all" @@ -321,12 +330,13 @@ "additionalProperties": false }, { + "description": "Queries a PoolReserve by index", "type": "object", "required": [ - "pool_reverses" + "pool_reserves" ], "properties": { - "pool_reverses": { + "pool_reserves": { "type": "object", "required": [ "fee", @@ -356,6 +366,7 @@ "additionalProperties": false }, { + "description": "Queries the simulated result of a multihop swap", "type": "object", "required": [ "estimate_multi_hop_swap" @@ -364,7 +375,7 @@ "estimate_multi_hop_swap": { "type": "object", "required": [ - "amount_id", + "amount_in", "creator", "exit_limit_price", "pick_best_route", @@ -372,7 +383,7 @@ "routes" ], "properties": { - "amount_id": { + "amount_in": { "$ref": "#/definitions/Int128" }, "creator": { @@ -399,6 +410,7 @@ "additionalProperties": false }, { + "description": "Queries the simulated result of a PlaceLimit order", "type": "object", "required": [ "estimate_place_limit_order" @@ -407,6 +419,7 @@ "estimate_place_limit_order": { "type": "object", "required": [ + "amount_in", "creator", "order_type", "receiver", @@ -415,6 +428,9 @@ "token_out" ], "properties": { + "amount_in": { + "$ref": "#/definitions/Int128" + }, "creator": { "type": "string" }, @@ -443,7 +459,8 @@ "type": "string" }, "tick_index_in_to_out": { - "$ref": "#/definitions/Uint128" + "type": "integer", + "format": "int64" }, "token_in": { "type": "string" @@ -457,6 +474,7 @@ "additionalProperties": false }, { + "description": "Queries a pool by pair, tick and fee", "type": "object", "required": [ "pool" @@ -488,12 +506,13 @@ "additionalProperties": false }, { + "description": "Queries a pool by ID", "type": "object", "required": [ - "pool_by_i_d" + "pool_by_id" ], "properties": { - "pool_by_i_d": { + "pool_by_id": { "type": "object", "required": [ "pool_id" @@ -510,6 +529,7 @@ "additionalProperties": false }, { + "description": "Queries a PoolMetadata by ID", "type": "object", "required": [ "pool_metadata" @@ -532,6 +552,7 @@ "additionalProperties": false }, { + "description": "Queries a list of PoolMetadata items.", "type": "object", "required": [ "pool_metadata_all" @@ -565,54 +586,43 @@ "description": "An implementation of i128 that is using strings for JSON encoding/decoding, such that the full i128 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 `i128` to get the value out:\n\n``` # use cosmwasm_std::Int128; let a = Int128::from(258i128); assert_eq!(a.i128(), 258); ```", "type": "string" }, - "LimitOrderTrancheUser": { - "type": "object", - "required": [ - "address", - "order_type", - "shares_cancelled", - "shares_owned", - "shares_withdrawn", - "tick_index_taker_to_maker", - "trade_pair_id", - "tranche_key" - ], - "properties": { - "address": { - "type": "string" - }, - "order_type": { - "$ref": "#/definitions/LimitOrderType" - }, - "shares_cancelled": { - "$ref": "#/definitions/Int128" - }, - "shares_owned": { - "$ref": "#/definitions/Int128" + "LimitOrderType": { + "oneOf": [ + { + "description": "Good-til-Cancelled limit orders are hybrid maker and taker limit orders. They will attempt to trade the supplied AmountIn at the TickIndex or better. However, if they total AmountIn cannot be traded at the limit price they are remaining amount will be placed as a maker limit order. The proceeds from the taker portion are deposited into the user’s account immediately, however, the proceeds from the maker portion must be explicitly withdrawn via WithdrawLimitOrder.", + "type": "string", + "enum": [ + "GOOD_TIL_CANCELLED" + ] }, - "shares_withdrawn": { - "$ref": "#/definitions/Int128" + { + "description": "Fill-or-Kill limit orders are taker limit orders that either successfully swap 100% of the supplied AmountIn or return an error. If there is insufficient liquidity to complete the trade at or above the supplied TickIndex a Fill-or-Kill order will return an error `codespace: dex, code: 1134` (https://github.com/neutron-org/neutron/blob/main/x/dex/types/errors.go#L107 ErrGoodTilOrderWithoutExpiration).", + "type": "string", + "enum": [ + "FILL_OR_KILL" + ] }, - "tick_index_taker_to_maker": { - "type": "integer", - "format": "int64" + { + "description": "Immediate-or-Cancel limit orders are taker orders that will swap as much as of the AmountIn as possible given available liquidity above the supplied TickIndex. Unlike Fill-or-Kill orders they will still successfully complete even if they are only able to partially trade through the AmountIn at the TickIndex or better.", + "type": "string", + "enum": [ + "IMMEDIATE_OR_CANCEL" + ] }, - "trade_pair_id": { - "$ref": "#/definitions/TradePairID" + { + "description": "Just-in-Time limit orders are an advanced maker limit order that provides tradeable liquidity for exactly one block. At the end of the same block in which the Just-in-Time order was submitted the order is canceled and any untraded portion will no longer be usable as active liquidity.", + "type": "string", + "enum": [ + "JUST_IN_TIME" + ] }, - "tranche_key": { - "type": "string" + { + "description": "Good-til-Time limit order function exactly the same as Good-til-Cancelled limit orders first trying to trade as a taker limit order and then placing any remaining amount as a maker limit order. However, the maker portion of the limit order has a specified ExpirationTime. After the ExpirationTime the order will be cancelled and can no longer be traded against. When withdrawing a Good-til-Time limit order the user will receive both the successfully traded portion of the limit order (TokenOut) as well as any remaining untraded amount (TokenIn).", + "type": "string", + "enum": [ + "GOOD_TIL_TIME" + ] } - } - }, - "LimitOrderType": { - "type": "string", - "enum": [ - "GoodTillCancel", - "FillOrKill", - "ImmediateOrCancel", - "JustInTime", - "GoodTilTime" ] }, "MultiHopRoute": { @@ -676,28 +686,9 @@ ], "properties": { "i": { - "$ref": "#/definitions/Uint128" - } - } - }, - "TradePairID": { - "type": "object", - "required": [ - "maker_denom", - "taker_denom" - ], - "properties": { - "maker_denom": { - "type": "string" - }, - "taker_denom": { "type": "string" } } - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "type": "string" } } } diff --git a/contracts/dex_stargate/schema/query_msg.json b/contracts/dex_stargate/schema/query_msg.json index f82f3d5..a742b14 100644 --- a/contracts/dex_stargate/schema/query_msg.json +++ b/contracts/dex_stargate/schema/query_msg.json @@ -168,12 +168,16 @@ "all_user_deposits": { "type": "object", "required": [ - "address" + "address", + "include_pool_data" ], "properties": { "address": { "type": "string" }, + "include_pool_data": { + "type": "boolean" + }, "pagination": { "anyOf": [ { diff --git a/contracts/reflect/schema/execute_msg.json b/contracts/reflect/schema/execute_msg.json index 0f6b741..466e8ef 100644 --- a/contracts/reflect/schema/execute_msg.json +++ b/contracts/reflect/schema/execute_msg.json @@ -497,6 +497,328 @@ } } }, + "DepositOption": { + "type": "object", + "required": [ + "disable_swap" + ], + "properties": { + "disable_swap": { + "type": "boolean" + } + } + }, + "DexMsg": { + "oneOf": [ + { + "description": "Deposit provides liquidity to a specific trading pair by depositing tokens at a specific price into one or both sides of the pair in “a liquidity pool”", + "type": "object", + "required": [ + "deposit" + ], + "properties": { + "deposit": { + "type": "object", + "required": [ + "amounts_a", + "amounts_b", + "fees", + "options", + "receiver", + "tick_indexes_a_to_b", + "token_a", + "token_b" + ], + "properties": { + "amounts_a": { + "description": "Amounts of tokenA to deposit", + "type": "array", + "items": { + "$ref": "#/definitions/Uint128" + } + }, + "amounts_b": { + "description": "Amounts of tokenB to deposit", + "type": "array", + "items": { + "$ref": "#/definitions/Uint128" + } + }, + "fees": { + "description": "Fees to use for each deposit", + "type": "array", + "items": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "options": { + "description": "Additional deposit options", + "type": "array", + "items": { + "$ref": "#/definitions/DepositOption" + } + }, + "receiver": { + "description": "The account to which PoolShares will be issued", + "type": "string" + }, + "tick_indexes_a_to_b": { + "description": "Tick indexes to deposit at defined in terms of TokenA to TokenB (ie. TokenA is on the left)", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + "token_a": { + "description": "Denom for one side of the deposit", + "type": "string" + }, + "token_b": { + "description": "Denom for the opposing side of the deposit", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Withdraw is used to redeem PoolShares for the user’s pro-rata portion of tokens within a liquidity pool. Users can withdraw from a pool at any time", + "type": "object", + "required": [ + "withdrawal" + ], + "properties": { + "withdrawal": { + "type": "object", + "required": [ + "fees", + "receiver", + "shares_to_remove", + "tick_indexes_a_to_b", + "token_a", + "token_b" + ], + "properties": { + "fees": { + "description": "Fee for the target LiquidityPools", + "type": "array", + "items": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "receiver": { + "description": "The account to which the tokens are credited", + "type": "string" + }, + "shares_to_remove": { + "description": "Amount of shares to remove from each pool", + "type": "array", + "items": { + "$ref": "#/definitions/Uint128" + } + }, + "tick_indexes_a_to_b": { + "description": "Tick indexes of the target LiquidityPools defined in terms of TokenA to TokenB (ie. TokenA is on the left)", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + "token_a": { + "description": "Denom for one side of the deposit", + "type": "string" + }, + "token_b": { + "description": "Denom for the opposing side of the deposit", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "PlaceLimitOrder provides the primary mechanism for trading on the Duality Dex. Limit orders can provide liquidity to the Dex (“Maker Limit Orders”) and/or can be used to trade against preexisting liquidity (“Taker Limit Orders”)", + "type": "object", + "required": [ + "place_limit_order" + ], + "properties": { + "place_limit_order": { + "type": "object", + "required": [ + "amount_in", + "order_type", + "receiver", + "tick_index_in_to_out", + "token_in", + "token_out" + ], + "properties": { + "amount_in": { + "description": "Amount of TokenIn to be traded", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "expiration_time": { + "description": "Expiration time for order. Only valid for GOOD_TIL_TIME limit orders", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "max_amount_out": { + "description": "Maximum amount of TokenB can be bought. For everything except JUST_IN_TIME OrderType", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "order_type": { + "description": "Type of limit order to be used. Must be one of: GOOD_TIL_CANCELLED, FILL_OR_KILL, IMMEDIATE_OR_CANCEL, JUST_IN_TIME, or GOOD_TIL_TIME", + "allOf": [ + { + "$ref": "#/definitions/LimitOrderType" + } + ] + }, + "receiver": { + "description": "Account to which TokenOut is credited or that will be allowed to withdraw or cancel a maker order", + "type": "string" + }, + "tick_index_in_to_out": { + "description": "Limit tick for a limit order, specified in terms of TokenIn to TokenOut", + "type": "integer", + "format": "int64" + }, + "token_in": { + "description": "Token being “sold”", + "type": "string" + }, + "token_out": { + "description": "Token being “bought”", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "WithdrawFilledLimitOrder. Once a limit order has been filled – either partially or in its entirety, it can be withdrawn at any time. Withdrawing from a limit order credits all available proceeds to the user. Withdraw can be called on a limit order multiple times as new proceeds become available", + "type": "object", + "required": [ + "withdraw_filled_limit_order" + ], + "properties": { + "withdraw_filled_limit_order": { + "type": "object", + "required": [ + "tranche_key" + ], + "properties": { + "tranche_key": { + "description": "TrancheKey for the target limit order", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "CancelLimitOrder. Standard Taker limit orders (Good-til-cancelled & Good-til-Time) can be canceled at any time if they have not been completely filled", + "type": "object", + "required": [ + "cancel_limit_order" + ], + "properties": { + "cancel_limit_order": { + "type": "object", + "required": [ + "tranche_key" + ], + "properties": { + "tranche_key": { + "description": "TrancheKey for the target limit order", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "MultiHopSwap provides a swapping mechanism to achieve better prices by routing through a series of pools", + "type": "object", + "required": [ + "multi_hop_swap" + ], + "properties": { + "multi_hop_swap": { + "type": "object", + "required": [ + "amount_in", + "exit_limit_price", + "pick_best_route", + "receiver", + "routes" + ], + "properties": { + "amount_in": { + "description": "Amount of TokenIn to swap", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "exit_limit_price": { + "description": "Minimum price that that must be satisfied for a route to succeed", + "allOf": [ + { + "$ref": "#/definitions/PrecDec" + } + ] + }, + "pick_best_route": { + "description": "If true all routes are run and the route with the best price is used", + "type": "boolean" + }, + "receiver": { + "description": "Account to which TokenOut is credited", + "type": "string" + }, + "routes": { + "description": "Array of possible routes", + "type": "array", + "items": { + "$ref": "#/definitions/MultiHopRoute" + } + } + } + } + }, + "additionalProperties": false + } + ] + }, "DistributionMsg": { "description": "The message types of the distribution module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto", "oneOf": [ @@ -820,6 +1142,45 @@ } } }, + "LimitOrderType": { + "oneOf": [ + { + "description": "Good-til-Cancelled limit orders are hybrid maker and taker limit orders. They will attempt to trade the supplied AmountIn at the TickIndex or better. However, if they total AmountIn cannot be traded at the limit price they are remaining amount will be placed as a maker limit order. The proceeds from the taker portion are deposited into the user’s account immediately, however, the proceeds from the maker portion must be explicitly withdrawn via WithdrawLimitOrder.", + "type": "string", + "enum": [ + "GOOD_TIL_CANCELLED" + ] + }, + { + "description": "Fill-or-Kill limit orders are taker limit orders that either successfully swap 100% of the supplied AmountIn or return an error. If there is insufficient liquidity to complete the trade at or above the supplied TickIndex a Fill-or-Kill order will return an error `codespace: dex, code: 1134` (https://github.com/neutron-org/neutron/blob/main/x/dex/types/errors.go#L107 ErrGoodTilOrderWithoutExpiration).", + "type": "string", + "enum": [ + "FILL_OR_KILL" + ] + }, + { + "description": "Immediate-or-Cancel limit orders are taker orders that will swap as much as of the AmountIn as possible given available liquidity above the supplied TickIndex. Unlike Fill-or-Kill orders they will still successfully complete even if they are only able to partially trade through the AmountIn at the TickIndex or better.", + "type": "string", + "enum": [ + "IMMEDIATE_OR_CANCEL" + ] + }, + { + "description": "Just-in-Time limit orders are an advanced maker limit order that provides tradeable liquidity for exactly one block. At the end of the same block in which the Just-in-Time order was submitted the order is canceled and any untraded portion will no longer be usable as active liquidity.", + "type": "string", + "enum": [ + "JUST_IN_TIME" + ] + }, + { + "description": "Good-til-Time limit order function exactly the same as Good-til-Cancelled limit orders first trying to trade as a taker limit order and then placing any remaining amount as a maker limit order. However, the maker portion of the limit order has a specified ExpirationTime. After the ExpirationTime the order will be cancelled and can no longer be traded against. When withdrawing a Good-til-Time limit order the user will receive both the successfully traded portion of the limit order (TokenOut) as well as any remaining untraded amount (TokenIn).", + "type": "string", + "enum": [ + "GOOD_TIL_TIME" + ] + } + ] + }, "MsgExecuteContract": { "description": "MsgExecuteContract defines a call to the contract execution", "type": "object", @@ -838,6 +1199,20 @@ } } }, + "MultiHopRoute": { + "type": "object", + "required": [ + "hops" + ], + "properties": { + "hops": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "NeutronMsg": { "description": "A number of Custom messages that can call into the Neutron bindings.", "oneOf": [ @@ -1434,6 +1809,19 @@ } }, "additionalProperties": false + }, + { + "description": "Dex messages", + "type": "object", + "required": [ + "dex" + ], + "properties": { + "dex": { + "$ref": "#/definitions/DexMsg" + } + }, + "additionalProperties": false } ] }, @@ -1539,6 +1927,17 @@ } } }, + "PrecDec": { + "type": "object", + "required": [ + "i" + ], + "properties": { + "i": { + "type": "string" + } + } + }, "ProposalExecuteMessage": { "description": "ProposalExecuteMessage defines the struct for sdk47 compatible admin proposal.", "type": "object",