diff --git a/.github/workflows/lint-format.yml b/.github/workflows/lint-format.yml index 9bcf1ab5..882c6aad 100644 --- a/.github/workflows/lint-format.yml +++ b/.github/workflows/lint-format.yml @@ -14,6 +14,11 @@ jobs: - name: Checkout sources uses: actions/checkout@v3 + - name: Set up Go 1.21.6 + uses: actions/setup-go@v5 + with: + go-version: "1.21.6" + - name: Install cargo make uses: davidB/rust-cargo-make@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4417af0e..ddf68c3f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,13 +15,16 @@ jobs: - name: Checkout sources uses: actions/checkout@v3 - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 + - name: Set up Go 1.21.6 + uses: actions/setup-go@v5 with: - profile: minimal - toolchain: 1.69.0 - target: wasm32-unknown-unknown - override: true + go-version: "1.21.6" + + - name: Install cargo make + uses: davidB/rust-cargo-make@v1 + + - name: Install stable toolchain + run: cargo make install-stable - name: Run unit tests uses: actions-rs/cargo@v1 @@ -51,7 +54,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --locked --test osmosis_tests --features osmosis-test-tube + args: --locked --test osmosis_tests --all-features env: RUST_BACKTRACE: 1 @@ -59,7 +62,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --locked --test astroport_tests --features osmosis-test-tube + args: --locked --test astroport_tests --all-features env: RUST_BACKTRACE: 1 @@ -67,6 +70,6 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --locked --test osmosis_proptests + args: --locked --test osmosis_proptests --all-features env: RUST_BACKTRACE: 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index b383845b..9ab5a7fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [0.5.2] - 2024-02-13 + +### Changed + +- Deprecated `implemenations` module in favor of new crates `cw-dex-astroport` and `cw-dex-osmosis`. + - This is to avoid breaking changes in `cw-dex` when one of the implementations change. + # [0.5.1] - 2024-02-06 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 625c345d..d22ffaad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,26 +51,26 @@ checksum = "423502406a307052f6877030f48b5fb4e9fb338fc5e7c8ca1064210def52876b" dependencies = [ "astroport 2.9.0", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw20 1.1.1", + "cw-storage-plus 1.2.0", + "cw20 1.1.2", "schemars", "serde", ] [[package]] name = "apollo-cw-multi-test" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b88d6037608a781a95ab1125941e2358c37272dcf0d4613de795b81b6ffbf3" +checksum = "f79f4204575175473a9b7fff8083596d09e6edb07469d2a4176846b353b2d1ef" dependencies = [ "anyhow", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "cw-utils 1.0.2", "derivative", - "itertools", + "itertools 0.10.5", "k256 0.11.6", - "osmosis-std", + "osmosis-std 0.22.0", "prost 0.9.0", "regex", "schemars", @@ -87,7 +87,7 @@ dependencies = [ "apollo-cw-asset", "cosmwasm-schema", "cosmwasm-std", - "cw20 1.1.1", + "cw20 1.1.2", "regex", ] @@ -113,24 +113,25 @@ dependencies = [ "cw-storage-plus 0.15.1", "cw-utils 0.15.1", "cw20 0.15.1", - "itertools", + "itertools 0.10.5", "uint", ] [[package]] name = "astroport" -version = "3.6.1" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195a7441515817c0d114ec3bebe9faa21393781f796c179c38c75e3cfb9fb4ec" +checksum = "c001a7f97db88ffe6fc6cca97bbdbfe926e55599184921ff7e72cd47559440de" dependencies = [ "astroport-circular-buffer", "cosmwasm-schema", "cosmwasm-std", + "cw-asset", "cw-storage-plus 0.15.1", "cw-utils 1.0.2", "cw20 0.15.1", "cw3", - "itertools", + "itertools 0.10.5", "uint", ] @@ -157,7 +158,7 @@ dependencies = [ "cosmwasm-std", "cw-storage-plus 0.15.1", "cw2 0.15.1", - "itertools", + "itertools 0.10.5", "protobuf", "thiserror", ] @@ -193,19 +194,36 @@ dependencies = [ "cw20 0.15.1", ] +[[package]] +name = "astroport-incentives" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba05c27479d2885ba313086aa0b7d09284f1393f1ebb6d385f96d93b3c6fb72a" +dependencies = [ + "astroport 3.11.1", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "cw-utils 1.0.2", + "cw2 1.1.1", + "cw20 1.1.2", + "itertools 0.11.0", + "thiserror", +] + [[package]] name = "astroport-liquidity-manager" -version = "1.0.3" +version = "1.0.3-astroport-v2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5673fe63b0284e30d1b456dea067cfaa82d2be6eafe5468cc0442917d49a04" +checksum = "ae4bf7689e7c37cfecc200aab3401c1ff6a507cccc9fb1baadfa71a73addaa2f" dependencies = [ - "astroport 3.6.1", + "astroport 2.9.0", "astroport-factory", "astroport-pair", - "astroport-pair-stable 3.3.0", + "astroport-pair-stable", "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "cw20 0.15.1", "cw20-base 0.15.1", "thiserror", @@ -244,15 +262,14 @@ dependencies = [ [[package]] name = "astroport-pair" -version = "1.5.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd96bc64722440636ed6267a6945ccce076231a08467d6d46a4af4c4ff062c69" +checksum = "e760b91eaf269bb2843b75b34eb73d474374bd2ebefbbe3cdb0a58d69959573b" dependencies = [ - "astroport 3.6.1", + "astroport 2.9.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 0.15.1", - "cw-utils 1.0.2", "cw2 0.15.1", "cw20 0.15.1", "integer-sqrt", @@ -274,15 +291,15 @@ dependencies = [ "cw-utils 0.15.1", "cw2 0.15.1", "cw20 0.15.1", - "itertools", + "itertools 0.10.5", "thiserror", ] [[package]] name = "astroport-pair-stable" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a262f2b6916e2a83808b246ff16cb2306a416e88b15a47ddbea5f8b666b1a4" +checksum = "d052966163fc2dd3eb46ae3c948ee7032a28726e046bc44431f9b488cb1dba90" dependencies = [ "astroport 2.9.0", "cosmwasm-schema", @@ -291,25 +308,7 @@ dependencies = [ "cw-utils 1.0.2", "cw2 0.15.1", "cw20 0.15.1", - "itertools", - "thiserror", -] - -[[package]] -name = "astroport-pair-stable" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ac52657fa25194936d5218a258c2c041df00f0647e954a23f35e99b730f92b" -dependencies = [ - "astroport 3.6.1", - "astroport-circular-buffer", - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 0.15.1", - "cw-utils 1.0.2", - "cw2 0.15.1", - "cw20 0.15.1", - "itertools", + "itertools 0.10.5", "thiserror", ] @@ -347,14 +346,15 @@ dependencies = [ [[package]] name = "astroport-test-contract" -version = "0.1.0" +version = "0.2.0" dependencies = [ "apollo-cw-asset", "cosmwasm-schema", "cosmwasm-std", "cw-dex", + "cw-dex-astroport", "cw-dex-test-contract", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "thiserror", ] @@ -411,18 +411,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "syn 2.0.48", ] [[package]] @@ -476,40 +465,44 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bindgen" -version = "0.60.1" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cexpr", "clang-sys", - "clap", - "env_logger", + "itertools 0.11.0", "lazy_static", "lazycell", "log", - "peeking_take_while", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", + "syn 2.0.48", "which", ] [[package]] name = "bip32" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30ed1d6f8437a487a266c8293aeb95b61a23261273e3e02912cdb8b68bf798b" +checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" dependencies = [ "bs58", "hmac", - "k256 0.11.6", - "once_cell", - "pbkdf2", + "k256 0.13.1", "rand_core 0.6.4", "ripemd", "sha2 0.10.8", @@ -564,17 +557,17 @@ dependencies = [ [[package]] name = "bnum" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128a44527fc0d6abf05f9eda748b9027536e12dff93f5acc8449f51583309350" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" [[package]] name = "bs58" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.9.9", + "sha2 0.10.8", ] [[package]] @@ -594,6 +587,9 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "cc" @@ -639,30 +635,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_lex", - "indexmap", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "config" version = "0.13.3" @@ -706,30 +678,30 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cosmos-sdk-proto" -version = "0.14.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20b42021d8488665b1a0d9748f1f81df7235362d194f44481e2e61bf376b77b4" +checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ - "prost 0.11.9", - "prost-types", + "prost 0.12.3", + "prost-types 0.12.3", "tendermint-proto", ] [[package]] name = "cosmrs" -version = "0.9.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3903590099dcf1ea580d9353034c9ba1dbf55d1389a5bd2ade98535c3445d1f9" +checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea" dependencies = [ "bip32", "cosmos-sdk-proto", - "ecdsa 0.14.8", + "ecdsa 0.16.8", "eyre", - "getrandom", - "k256 0.11.6", + "k256 0.13.1", "rand_core 0.6.4", "serde", "serde_json", + "signature 2.1.0", "subtle-encoding", "tendermint", "tendermint-rpc", @@ -738,11 +710,12 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fb22494cf7d23d0c348740e06e5c742070b2991fd41db77bba0bcfbae1a723" +checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" dependencies = [ "digest 0.10.7", + "ecdsa 0.16.8", "ed25519-zebra", "k256 0.13.1", "rand_core 0.6.4", @@ -751,18 +724,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e199424486ea97d6b211db6387fd72e26b4a439d40cc23140b2d8305728055b" +checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef683a9c1c4eabd6d31515719d0d2cc66952c4c87f7eb192bfc90384517dc34" +checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -773,9 +746,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9567025acbb4c0c008178393eb53b3ac3c2e492c25949d3bf415b9cbe80772d8" +checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" dependencies = [ "proc-macro2", "quote", @@ -784,11 +757,12 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d89d680fb60439b7c5947b15f9c84b961b88d1f8a3b20c4bd178a3f87db8bae" +checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" dependencies = [ "base64 0.21.5", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", @@ -799,6 +773,7 @@ dependencies = [ "serde", "serde-json-wasm", "sha2 0.10.8", + "static_assertions", "thiserror", ] @@ -861,15 +836,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct", -] - [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -883,13 +849,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "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 1.2.0", + "cw20 1.1.2", + "thiserror", +] + [[package]] name = "cw-dex" -version = "0.5.1" +version = "0.5.2" dependencies = [ "apollo-cw-asset", "apollo-utils", "astroport 2.9.0", + "astroport 3.11.1", "cosmwasm-schema", "cosmwasm-std", "cw-dex-test-contract", @@ -897,22 +900,63 @@ dependencies = [ "cw-it", "cw-utils 1.0.2", "cw2 1.1.1", - "cw20 1.1.1", + "cw20 1.1.2", "cw20-base 1.1.1", - "osmosis-std", + "osmosis-std 0.19.2", "proptest", "test-case", "thiserror", ] [[package]] -name = "cw-dex-test-contract" +name = "cw-dex-astroport" version = "0.1.0" dependencies = [ "apollo-cw-asset", + "apollo-utils", + "astroport 2.9.0", + "astroport 3.11.1", "cosmwasm-schema", "cosmwasm-std", "cw-dex", + "cw-dex-test-contract", + "cw-dex-test-helpers", + "cw-it", + "cw-utils 1.0.2", + "cw2 1.1.1", + "cw20 1.1.2", + "cw20-base 1.1.1", + "proptest", + "test-case", +] + +[[package]] +name = "cw-dex-osmosis" +version = "0.1.0" +dependencies = [ + "apollo-cw-asset", + "apollo-utils", + "cosmwasm-schema", + "cosmwasm-std", + "cw-dex", + "cw-dex-test-contract", + "cw-dex-test-helpers", + "cw-it", + "cw-utils 1.0.2", + "cw20 1.1.2", + "cw20-base 1.1.1", + "osmosis-std 0.22.0", + "proptest", + "test-case", +] + +[[package]] +name = "cw-dex-test-contract" +version = "0.2.0" +dependencies = [ + "apollo-cw-asset", + "cosmwasm-schema", + "cosmwasm-std", ] [[package]] @@ -926,28 +970,30 @@ dependencies = [ "cosmwasm-std", "cw-dex-test-contract", "cw-it", - "cw20 1.1.1", + "cw20 1.1.2", "cw20-base 1.1.1", ] [[package]] name = "cw-it" -version = "0.2.3" +version = "0.3.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f452b759fc448ec05d20dc70f25dda8b83ba0a7c994049d27556fd1813a5ad0d" +checksum = "8323a657163a204179a9a7a4a418794aa71f9c789b58b8c91974e2691f7db408" dependencies = [ "anyhow", "apollo-cw-multi-test", "apollo-utils", "astroport 2.9.0", + "astroport 3.11.1", "astroport-factory", "astroport-generator", + "astroport-incentives", "astroport-liquidity-manager", "astroport-maker", "astroport-native-coin-registry", "astroport-pair", "astroport-pair-concentrated", - "astroport-pair-stable 2.1.2", + "astroport-pair-stable", "astroport-router", "astroport-staking", "astroport-token", @@ -958,14 +1004,13 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw20 0.15.1", - "osmosis-std", + "osmosis-std 0.22.0", "osmosis-test-tube", "paste", "proptest", - "prost 0.11.9", + "prost 0.12.3", "regex", "serde", - "serde_json", "strum", "test-tube", "thiserror", @@ -984,9 +1029,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ "cosmwasm-std", "schemars", @@ -1073,7 +1118,7 @@ checksum = "9431d14f64f49e41c6ef5561ed11a5391c417d0cb16455dea8cdcb9037a8d197" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "schemars", "serde", "thiserror", @@ -1094,9 +1139,9 @@ dependencies = [ [[package]] name = "cw20" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786e9da5e937f473cecd2463e81384c1af65d0f6398bbd851be7655487c55492" +checksum = "526e39bb20534e25a1cd0386727f0038f4da294e5e535729ba3ef54055246abd" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -1131,10 +1176,10 @@ checksum = "09558f87fd3d5e4a479761051b3f98ee2fa723d9e484b5679b6058ad0eadf8f1" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "cw-utils 1.0.2", "cw2 1.1.1", - "cw20 1.1.1", + "cw20 1.1.2", "schemars", "semver", "serde", @@ -1150,7 +1195,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-utils 1.0.2", - "cw20 1.1.1", + "cw20 1.1.2", "schemars", "serde", "thiserror", @@ -1254,21 +1299,23 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "signature 1.6.4", + "pkcs8 0.10.2", + "signature 2.1.0", ] [[package]] -name = "ed25519-dalek" -version = "1.0.1" +name = "ed25519-consensus" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" dependencies = [ - "curve25519-dalek", - "ed25519", + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", "sha2 0.9.9", "zeroize", ] @@ -1334,16 +1381,12 @@ dependencies = [ ] [[package]] -name = "env_logger" -version = "0.9.3" +name = "encoding_rs" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "cfg-if", ] [[package]] @@ -1431,7 +1474,6 @@ checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1454,34 +1496,12 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" -[[package]] -name = "futures-executor" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" -[[package]] -name = "futures-macro" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "futures-sink" version = "0.3.29" @@ -1500,16 +1520,11 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ - "futures-channel", "futures-core", - "futures-io", - "futures-macro", "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -1598,45 +1613,12 @@ dependencies = [ "ahash", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.3" @@ -1701,12 +1683,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.27" @@ -1731,41 +1707,18 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-proxy" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" -dependencies = [ - "bytes", - "futures", - "headers", - "http", - "hyper", - "hyper-rustls", - "rustls-native-certs", - "tokio", - "tokio-rustls", - "tower-service", - "webpki", -] - [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "ct-logs", "futures-util", + "http", "hyper", - "log", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", - "webpki", - "webpki-roots", ] [[package]] @@ -1800,14 +1753,29 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" dependencies = [ - "num-traits", + "num-traits", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", ] [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] @@ -1848,7 +1816,6 @@ dependencies = [ "ecdsa 0.14.8", "elliptic-curve 0.12.3", "sha2 0.10.8", - "sha3", ] [[package]] @@ -1865,15 +1832,6 @@ dependencies = [ "signature 2.1.0", ] -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -2001,7 +1959,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi", "libc", ] @@ -2051,12 +2009,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "osmosis-std" version = "0.19.2" @@ -2065,9 +2017,25 @@ checksum = "798fade51443a0e07eb25b59a11b320b9e8f03e6e8fbe14c520258f04742fe13" dependencies = [ "chrono", "cosmwasm-std", - "osmosis-std-derive", + "osmosis-std-derive 0.16.2", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", + "schemars", + "serde", + "serde-cw-value", +] + +[[package]] +name = "osmosis-std" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8641c376f01f5af329dc2a34e4f5527eaeb0bde18cda8d86fed958d04c86159c" +dependencies = [ + "chrono", + "cosmwasm-std", + "osmosis-std-derive 0.20.1", + "prost 0.12.3", + "prost-types 0.12.3", "schemars", "serde", "serde-cw-value", @@ -2079,38 +2047,52 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f47f0b2f22adb341bb59e5a3a1b464dde033181954bd055b9ae86d6511ba465b" dependencies = [ - "itertools", + "itertools 0.10.5", + "proc-macro2", + "prost-types 0.11.9", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "osmosis-std-derive" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ebdfd1bc8ed04db596e110c6baa9b174b04f6ed1ec22c666ddc5cb3fa91bd7" +dependencies = [ + "itertools 0.10.5", "proc-macro2", - "prost-types", + "prost-types 0.11.9", "quote", "syn 1.0.109", ] [[package]] name = "osmosis-test-contract" -version = "0.1.0" +version = "0.2.0" dependencies = [ "apollo-cw-asset", "cosmwasm-schema", "cosmwasm-std", "cw-dex", + "cw-dex-osmosis", "cw-dex-test-contract", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "thiserror", ] [[package]] name = "osmosis-test-tube" -version = "19.2.0" +version = "22.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dde0a21f1323e7c78f46da4bd0b24149d26483785fb5b39f74016f3f524aad" +checksum = "a082b97136d15470a37aa758f227c865594590b69d74721248ed5adf59bf1ca2" dependencies = [ - "base64 0.13.1", + "base64 0.21.5", "bindgen", "cosmrs", "cosmwasm-std", - "osmosis-std", - "prost 0.11.9", + "osmosis-std 0.22.0", + "prost 0.12.3", "serde", "serde_json", "test-tube", @@ -2129,21 +2111,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "peg" version = "0.7.0" @@ -2208,7 +2175,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -2239,7 +2206,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -2280,6 +2247,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn 2.0.48", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2306,9 +2283,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2353,6 +2330,16 @@ dependencies = [ "prost-derive 0.11.9", ] +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive 0.12.3", +] + [[package]] name = "prost-derive" version = "0.9.0" @@ -2360,7 +2347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", @@ -2373,12 +2360,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "prost-types" version = "0.11.9" @@ -2388,6 +2388,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -2405,9 +2414,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2501,6 +2510,47 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "reqwest" +version = "0.11.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +dependencies = [ + "base64 0.21.5", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "rfc6979" version = "0.3.1" @@ -2524,17 +2574,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys", ] [[package]] @@ -2546,17 +2595,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "ripemd160" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "ron" version = "0.7.1" @@ -2605,29 +2643,47 @@ dependencies = [ [[package]] name = "rustls" -version = "0.19.1" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ - "base64 0.13.1", "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] name = "rustls-native-certs" -version = "0.5.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls", + "rustls-pemfile", "schannel", "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.5", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -2696,9 +2752,9 @@ dependencies = [ [[package]] name = "sct" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -2781,9 +2837,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" dependencies = [ "serde", ] @@ -2805,7 +2861,7 @@ checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -2838,18 +2894,19 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] -name = "sha1" -version = "0.10.6" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] @@ -2876,16 +2933,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - [[package]] name = "shlex" version = "1.2.0" @@ -2964,9 +3011,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" @@ -2994,12 +3041,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strum" version = "0.24.1" @@ -3037,6 +3078,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "syn" version = "1.0.109" @@ -3050,15 +3097,42 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.8.1" @@ -3074,28 +3148,28 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.23.9" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467f82178deeebcd357e1273a0c0b77b9a8a0313ef7c07074baebe99d87851f4" +checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" dependencies = [ - "async-trait", "bytes", + "digest 0.10.7", "ed25519", - "ed25519-dalek", + "ed25519-consensus", "flex-error", "futures", - "k256 0.11.6", + "k256 0.13.1", "num-traits", "once_cell", - "prost 0.11.9", - "prost-types", - "ripemd160", + "prost 0.12.3", + "prost-types 0.12.3", + "ripemd", "serde", "serde_bytes", "serde_json", "serde_repr", - "sha2 0.9.9", - "signature 1.6.4", + "sha2 0.10.8", + "signature 2.1.0", "subtle", "subtle-encoding", "tendermint-proto", @@ -3105,9 +3179,9 @@ dependencies = [ [[package]] name = "tendermint-config" -version = "0.23.9" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d42ee0abc27ef5fc34080cce8d43c189950d331631546e7dfb983b6274fa327" +checksum = "5a25dbe8b953e80f3d61789fbdb83bf9ad6c0ef16df5ca6546f49912542cc137" dependencies = [ "flex-error", "serde", @@ -3119,16 +3193,16 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.23.9" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ce80bf536476db81ecc9ebab834dc329c9c1509a694f211a73858814bfe023" +checksum = "2cc728a4f9e891d71adf66af6ecaece146f9c7a11312288a3107b3e1d6979aaf" dependencies = [ "bytes", "flex-error", "num-derive", "num-traits", - "prost 0.11.9", - "prost-types", + "prost 0.12.3", + "prost-types 0.12.3", "serde", "serde_bytes", "subtle-encoding", @@ -3137,24 +3211,23 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.23.9" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f14aafe3528a0f75e9f3f410b525617b2de16c4b7830a21f717eee62882ec60" +checksum = "dfbf0a4753b46a190f367337e0163d0b552a2674a6bac54e74f9f2cdcde2969b" dependencies = [ "async-trait", "bytes", "flex-error", "futures", "getrandom", - "http", - "hyper", - "hyper-proxy", - "hyper-rustls", "peg", "pin-project", + "reqwest", + "semver", "serde", "serde_bytes", "serde_json", + "subtle", "subtle-encoding", "tendermint", "tendermint-config", @@ -3168,15 +3241,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "termcolor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" -dependencies = [ - "winapi-util", -] - [[package]] name = "test-case" version = "3.2.1" @@ -3196,7 +3260,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3208,50 +3272,44 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "test-case-core", ] [[package]] name = "test-tube" -version = "0.1.7" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04de0d85f2438f0b64a5c135a1524564f2b89263cfbce011542446b6681d006f" +checksum = "09184c7655b2bdaf4517b06141a2e4c44360904f2706a05b24c831bd97ad1db6" dependencies = [ - "base64 0.13.1", + "base64 0.21.5", "cosmrs", "cosmwasm-std", - "osmosis-std", - "prost 0.11.9", + "osmosis-std 0.22.0", + "prost 0.12.3", "serde", "serde_json", "thiserror", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] @@ -3311,18 +3369,17 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -3432,9 +3489,9 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -3514,10 +3571,22 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.87" @@ -3536,7 +3605,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3557,25 +3626,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" -dependencies = [ - "webpki", -] - [[package]] name = "which" version = "4.4.2" @@ -3685,6 +3735,16 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -3711,5 +3771,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.48", ] diff --git a/Cargo.toml b/Cargo.toml index 46d5bf41..ab155578 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["cw-dex", "test-contracts/*", "test-helpers"] +members = ["cw-dex", "cw-dex-astroport", "cw-dex-osmosis", "test-contracts/*", "test-helpers"] resolver = "2" [workspace.package] @@ -14,7 +14,7 @@ rust-version = "1.64.0" [workspace.dependencies] cosmwasm-schema = "1.2.1" -cosmwasm-std = "1.2.1" +cosmwasm-std = "1.5.3" cosmwasm-storage = "1.2.1" cw-storage-plus = "1.0" cw2 = "1.0" @@ -25,14 +25,21 @@ schemars = "0.8.10" serde = { version = "1.0.145", default-features = false, features = ["derive"] } thiserror = { version = "1.0.31" } apollo-cw-asset = "0.1.1" -osmosis-std = "0.19.2" -cw-it = "0.2.3" -cw-dex = { path = "cw-dex" } +osmosis-std = "0.22.0" +cw-it = "0.3.0-rc.4" +apollo-utils = "0.1.0" +astroport = "2.9.0" +astroport_v3 = { package = "astroport", version = "3.11.1" } +test-case = "3.0.0" +proptest = "1.0.0" + +# Workspace packages +cw-dex = { path = "cw-dex", version = "0.5.2" } +cw-dex-astroport = { path = "cw-dex-astroport", version = "0.1.0" } +cw-dex-osmosis = { path = "cw-dex-osmosis", version = "0.1.0" } cw-dex-test-contract = { path = "test-contracts/package" } astroport-test-contract = { path = "test-contracts/astroport-test-contract" } cw-dex-test-helpers = { path = "test-helpers" } -apollo-utils = "0.1.0" -astroport = "=2.9.0" [profile.release] codegen-units = 1 diff --git a/Makefile.toml b/Makefile.toml index 118b80aa..90d450e4 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -4,10 +4,10 @@ skip_core_tasks = true [env] # If you bump this version, verify RUST_VERSION correctness -RUST_OPTIMIZER_VERSION = "0.13.0" +RUST_OPTIMIZER_VERSION = "0.15.0" # Use rust version from rust-optimizer Dockerfile (see https://github.com/CosmWasm/rust-optimizer/blob/main/Dockerfile#L1) # to be sure that we compile / test against the same version -RUST_VERSION = "1.69.0" +RUST_VERSION = "1.75.0" NIGHTLY_VERSION = "nightly-2023-08-29" [tasks.install-stable] @@ -54,7 +54,7 @@ args = ["fmt", "--all", "--","--verbose", "--check"] [tasks.deny] command = "cargo" -args = ["deny", "check"] +args = ["deny", "--all-features", "check"] [tasks.check] toolchain = "${RUST_VERSION}" @@ -142,6 +142,7 @@ toolchain = "${RUST_VERSION}" command = "cargo" args = [ "test", + "--all-features", "--lib" ] @@ -154,8 +155,7 @@ toolchain = "${RUST_VERSION}" command = "cargo" args = [ "test", - "--features", - "osmosis-test-tube", + "--all-features", "--test", "*", ] diff --git a/cw-dex-astroport/Cargo.toml b/cw-dex-astroport/Cargo.toml new file mode 100644 index 00000000..47fa60b6 --- /dev/null +++ b/cw-dex-astroport/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "cw-dex-astroport" +authors = ["Apollo Devs"] +description = "Implementation of the cw-dex API for the Astroport AMM" +edition = "2021" +license = "MPL-2.0" +repository = "https://github.com/apollodao/cw-dex" +version = "0.1.0" +readme = "README.md" + +[features] +default = [] +osmosis-test-tube = ["cw-it/osmosis-test-tube", "cw-dex-test-helpers/osmosis-test-tube"] +# backtraces = ["cosmwasm-std/backtraces", "osmosis-std/backtraces"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +cw-dex = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +apollo-cw-asset = { workspace = true, features = ["astroport"] } +cw-utils = { workspace = true } +cw20 = { workspace = true } +apollo-utils = { workspace = true } + +# Astroport +astroport = { workspace = true } +astroport_v3 = { workspace = true } +cw2 = { workspace = true } + +[dev-dependencies] +cw-it = { workspace = true, features = ["astroport", "multi-test", "astroport-multi-test"] } +test-case = { workspace = true } +cw-dex-test-contract = { workspace = true } +cw-dex-test-helpers = { workspace = true, features = ["astroport"] } +proptest = { workspace = true } +cw20-base = { workspace = true } +cw20 = { workspace = true } diff --git a/cw-dex/artifacts/astroport_factory.wasm b/cw-dex-astroport/artifacts/astroport_factory.wasm similarity index 100% rename from cw-dex/artifacts/astroport_factory.wasm rename to cw-dex-astroport/artifacts/astroport_factory.wasm diff --git a/cw-dex/artifacts/astroport_generator.wasm b/cw-dex-astroport/artifacts/astroport_generator.wasm similarity index 100% rename from cw-dex/artifacts/astroport_generator.wasm rename to cw-dex-astroport/artifacts/astroport_generator.wasm diff --git a/cw-dex-astroport/artifacts/astroport_incentives.wasm b/cw-dex-astroport/artifacts/astroport_incentives.wasm new file mode 100644 index 00000000..371ad055 Binary files /dev/null and b/cw-dex-astroport/artifacts/astroport_incentives.wasm differ diff --git a/cw-dex/artifacts/astroport_liquidity_helper.wasm b/cw-dex-astroport/artifacts/astroport_liquidity_helper.wasm similarity index 100% rename from cw-dex/artifacts/astroport_liquidity_helper.wasm rename to cw-dex-astroport/artifacts/astroport_liquidity_helper.wasm diff --git a/cw-dex/artifacts/astroport_liquidity_manager.wasm b/cw-dex-astroport/artifacts/astroport_liquidity_manager.wasm similarity index 100% rename from cw-dex/artifacts/astroport_liquidity_manager.wasm rename to cw-dex-astroport/artifacts/astroport_liquidity_manager.wasm diff --git a/cw-dex/artifacts/astroport_maker.wasm b/cw-dex-astroport/artifacts/astroport_maker.wasm similarity index 100% rename from cw-dex/artifacts/astroport_maker.wasm rename to cw-dex-astroport/artifacts/astroport_maker.wasm diff --git a/cw-dex/artifacts/astroport_native_coin_registry.wasm b/cw-dex-astroport/artifacts/astroport_native_coin_registry.wasm similarity index 100% rename from cw-dex/artifacts/astroport_native_coin_registry.wasm rename to cw-dex-astroport/artifacts/astroport_native_coin_registry.wasm diff --git a/cw-dex/artifacts/astroport_native_coin_wrapper.wasm b/cw-dex-astroport/artifacts/astroport_native_coin_wrapper.wasm similarity index 100% rename from cw-dex/artifacts/astroport_native_coin_wrapper.wasm rename to cw-dex-astroport/artifacts/astroport_native_coin_wrapper.wasm diff --git a/cw-dex/artifacts/astroport_oracle.wasm b/cw-dex-astroport/artifacts/astroport_oracle.wasm similarity index 100% rename from cw-dex/artifacts/astroport_oracle.wasm rename to cw-dex-astroport/artifacts/astroport_oracle.wasm diff --git a/cw-dex/artifacts/astroport_pair.wasm b/cw-dex-astroport/artifacts/astroport_pair.wasm similarity index 100% rename from cw-dex/artifacts/astroport_pair.wasm rename to cw-dex-astroport/artifacts/astroport_pair.wasm diff --git a/cw-dex/artifacts/astroport_pair_astro_xastro.wasm b/cw-dex-astroport/artifacts/astroport_pair_astro_xastro.wasm similarity index 100% rename from cw-dex/artifacts/astroport_pair_astro_xastro.wasm rename to cw-dex-astroport/artifacts/astroport_pair_astro_xastro.wasm diff --git a/cw-dex/artifacts/astroport_pair_concentrated.wasm b/cw-dex-astroport/artifacts/astroport_pair_concentrated.wasm similarity index 100% rename from cw-dex/artifacts/astroport_pair_concentrated.wasm rename to cw-dex-astroport/artifacts/astroport_pair_concentrated.wasm diff --git a/cw-dex/artifacts/astroport_pair_stable.wasm b/cw-dex-astroport/artifacts/astroport_pair_stable.wasm similarity index 100% rename from cw-dex/artifacts/astroport_pair_stable.wasm rename to cw-dex-astroport/artifacts/astroport_pair_stable.wasm diff --git a/cw-dex/artifacts/astroport_router.wasm b/cw-dex-astroport/artifacts/astroport_router.wasm similarity index 100% rename from cw-dex/artifacts/astroport_router.wasm rename to cw-dex-astroport/artifacts/astroport_router.wasm diff --git a/cw-dex/artifacts/astroport_staking.wasm b/cw-dex-astroport/artifacts/astroport_staking.wasm similarity index 100% rename from cw-dex/artifacts/astroport_staking.wasm rename to cw-dex-astroport/artifacts/astroport_staking.wasm diff --git a/cw-dex/artifacts/astroport_token.wasm b/cw-dex-astroport/artifacts/astroport_token.wasm similarity index 100% rename from cw-dex/artifacts/astroport_token.wasm rename to cw-dex-astroport/artifacts/astroport_token.wasm diff --git a/cw-dex/artifacts/astroport_vault.wasm b/cw-dex-astroport/artifacts/astroport_vault.wasm similarity index 100% rename from cw-dex/artifacts/astroport_vault.wasm rename to cw-dex-astroport/artifacts/astroport_vault.wasm diff --git a/cw-dex/artifacts/astroport_vesting.wasm b/cw-dex-astroport/artifacts/astroport_vesting.wasm similarity index 100% rename from cw-dex/artifacts/astroport_vesting.wasm rename to cw-dex-astroport/artifacts/astroport_vesting.wasm diff --git a/cw-dex/artifacts/astroport_whitelist.wasm b/cw-dex-astroport/artifacts/astroport_whitelist.wasm similarity index 100% rename from cw-dex/artifacts/astroport_whitelist.wasm rename to cw-dex-astroport/artifacts/astroport_whitelist.wasm diff --git a/cw-dex/artifacts/astroport_xastro_token.wasm b/cw-dex-astroport/artifacts/astroport_xastro_token.wasm similarity index 100% rename from cw-dex/artifacts/astroport_xastro_token.wasm rename to cw-dex-astroport/artifacts/astroport_xastro_token.wasm diff --git a/cw-dex/artifacts/checksums.txt b/cw-dex-astroport/artifacts/checksums.txt similarity index 94% rename from cw-dex/artifacts/checksums.txt rename to cw-dex-astroport/artifacts/checksums.txt index 7f264cb9..29c91e96 100644 --- a/cw-dex/artifacts/checksums.txt +++ b/cw-dex-astroport/artifacts/checksums.txt @@ -15,3 +15,4 @@ dbf959bcdb049bfcf7592a8745b3220a327fee352f2f8aa273879483a435af05 astroport_vest 713de64a97e24555a5b6775d1a65aa73a76e69e17ff871c1b6e024574b1fe39b astroport_whitelist.wasm e2d21ef6ceb77f1604e2b258e6485c82354ff8d281e63c51397402d37267bd92 astroport_generator.wasm 4acf2a1cf21633514af4566fe36b74736c6c17072e148b6e26e93dc3057e6a47 astroport_liquidity_manager.wasm +9bf67ed14b8272cd600e0496f87b3e5c3d8301cc4b03570090761f5c48efc095 astroport_incentives.wasm diff --git a/cw-dex/artifacts/checksums_intermediate.txt b/cw-dex-astroport/artifacts/checksums_intermediate.txt similarity index 100% rename from cw-dex/artifacts/checksums_intermediate.txt rename to cw-dex-astroport/artifacts/checksums_intermediate.txt diff --git a/cw-dex/artifacts/cw_dex_router.wasm b/cw-dex-astroport/artifacts/cw_dex_router.wasm similarity index 100% rename from cw-dex/artifacts/cw_dex_router.wasm rename to cw-dex-astroport/artifacts/cw_dex_router.wasm diff --git a/cw-dex/artifacts/cw_dex_test_contract.wasm b/cw-dex-astroport/artifacts/cw_dex_test_contract.wasm similarity index 100% rename from cw-dex/artifacts/cw_dex_test_contract.wasm rename to cw-dex-astroport/artifacts/cw_dex_test_contract.wasm diff --git a/cw-dex-astroport/src/lib.rs b/cw-dex-astroport/src/lib.rs new file mode 100644 index 00000000..66173e16 --- /dev/null +++ b/cw-dex-astroport/src/lib.rs @@ -0,0 +1,9 @@ +//! Pool and Staking implementations for Astroport + +mod pool; +mod staking; + +pub use pool::AstroportPool; +pub use staking::AstroportStaking; + +pub use {astroport, astroport_v3}; diff --git a/cw-dex-astroport/src/pool.rs b/cw-dex-astroport/src/pool.rs new file mode 100644 index 00000000..84d255fd --- /dev/null +++ b/cw-dex-astroport/src/pool.rs @@ -0,0 +1,347 @@ +//! Pool trait implementation for Astroport + +use std::str::FromStr; + +use apollo_cw_asset::{Asset, AssetInfo, AssetInfoBase, AssetList}; +use apollo_utils::iterators::IntoElementwise; +use astroport::liquidity_manager; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + to_json_binary, wasm_execute, Addr, CosmosMsg, Decimal, Deps, Env, Event, QuerierWrapper, + QueryRequest, Response, StdError, StdResult, Uint128, WasmMsg, WasmQuery, +}; +use cw20::Cw20ExecuteMsg; +use cw_utils::Expiration; + +use apollo_utils::assets::separate_natives_and_cw20s; +use astroport::asset::{Asset as AstroAsset, PairInfo}; +use astroport::factory::PairType; +use astroport::pair::{ + Cw20HookMsg as PairCw20HookMsg, ExecuteMsg as PairExecuteMsg, PoolResponse, + QueryMsg as PairQueryMsg, SimulationResponse, MAX_ALLOWED_SLIPPAGE, +}; +use astroport::querier::query_supply; +use cw_dex::traits::Pool; +use cw_dex::CwDexError; + +/// Represents an AMM pool on Astroport +#[cw_serde] +pub struct AstroportPool { + /// The address of the associated pair contract + pub pair_addr: Addr, + /// The address of the associated LP token contract + pub lp_token_addr: Addr, + /// The assets of the pool + pub pool_assets: Vec, + /// The type of pool represented: Constant product (*Xyk*) or *Stableswap* + pub pair_type: PairType, + /// The address of the Astroport liquidity manager contract + pub liquidity_manager: Addr, +} + +impl AstroportPool { + /// Creates a new instance of `AstroportPool` + /// + /// Arguments: + /// - `pair_addr`: The address of the pair contract associated with the pool + pub fn new(deps: Deps, pair_addr: Addr, liquidity_manager: Addr) -> StdResult { + let pair_info = deps + .querier + .query_wasm_smart::(pair_addr.clone(), &PairQueryMsg::Pair {})?; + + // Validate pair type. We only support XYK, stable swap, and PCL pools + match &pair_info.pair_type { + PairType::Custom(t) => match t.as_str() { + "concentrated" => Ok(()), + "astroport-pair-xyk-sale-tax" => Ok(()), + _ => Err(StdError::generic_err("Custom pair type is not supported")), + }, + _ => Ok(()), + }?; + + Ok(Self { + pair_addr, + lp_token_addr: pair_info.liquidity_token, + pool_assets: pair_info.asset_infos.into_elementwise(), + pair_type: pair_info.pair_type, + liquidity_manager, + }) + } + + /// Returns the matching pool given a LP token. + /// + /// Arguments: + /// - `lp_token`: Said LP token + /// - `astroport_liquidity_manager`: The Astroport liquidity manager + /// address. + pub fn get_pool_for_lp_token( + deps: Deps, + lp_token: &AssetInfo, + astroport_liquidity_manager: Addr, + ) -> Result { + match lp_token { + AssetInfo::Cw20(address) => { + // To figure out if the CW20 is a LP token, we need to check which address + // instantiated the CW20 and check if that address is an Astroport pair + // contract. + let contract_info = deps.querier.query_wasm_contract_info(address)?; + let creator_addr = deps.api.addr_validate(&contract_info.creator)?; + + // Try to create an `AstroportPool` object with the creator address. This will + // query the contract and assume that it is an Astroport pair + // contract. If it succeeds, the pool object will be returned. + // + // NB: This does NOT validate that the pool is registered with the Astroport + // factory, and that it is an "official" Astroport pool. + let pool = AstroportPool::new(deps, creator_addr, astroport_liquidity_manager)?; + + Ok(pool) + } + _ => Err(CwDexError::NotLpToken {}), + } + } + + /// Returns the total supply of the associated LP token + pub fn query_lp_token_supply(&self, querier: &QuerierWrapper) -> StdResult { + query_supply(querier, self.lp_token_addr.to_owned()) + } + + /// Queries the pair contract for the current pool state + pub fn query_pool_info(&self, querier: &QuerierWrapper) -> StdResult { + querier.query::(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.pair_addr.to_string(), + msg: to_json_binary(&PairQueryMsg::Pool {})?, + })) + } +} + +impl Pool for AstroportPool { + fn provide_liquidity( + &self, + _deps: Deps, + env: &Env, + assets: AssetList, + min_out: Uint128, + ) -> Result { + let (funds, cw20s) = separate_natives_and_cw20s(&assets); + + // Increase allowance on all Cw20s + let allowance_msgs: Vec = cw20s + .into_iter() + .map(|asset| { + Ok(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: asset.address, + msg: to_json_binary(&Cw20ExecuteMsg::IncreaseAllowance { + spender: self.liquidity_manager.to_string(), + amount: asset.amount, + expires: Some(Expiration::AtHeight(env.block.height + 1)), + })?, + funds: vec![], + })) + }) + .collect::>>()?; + + // Liquidity manager requires assets vec to contain all assets in the pool + let mut assets_vec = assets.to_vec(); + for pool_asset_info in &self.pool_assets { + if !assets_vec.iter().any(|x| &x.info == pool_asset_info) { + assets_vec.push(Asset::new(pool_asset_info.clone(), Uint128::zero())); + } + } + + // Create the provide liquidity message + let provide_liquidity_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.liquidity_manager.to_string(), + msg: to_json_binary(&liquidity_manager::ExecuteMsg::ProvideLiquidity { + pair_addr: self.pair_addr.to_string(), + min_lp_to_receive: Some(min_out), + pair_msg: astroport::pair::ExecuteMsg::ProvideLiquidity { + assets: assets_vec.into_elementwise(), + slippage_tolerance: Some(Decimal::from_str(MAX_ALLOWED_SLIPPAGE)?), + auto_stake: Some(false), + receiver: None, + }, + })?, + funds, + }); + + let event = Event::new("apollo/cw-dex/provide_liquidity") + .add_attribute("pair_addr", &self.pair_addr) + .add_attribute("assets", format!("{:?}", assets)); + + Ok(Response::new() + .add_messages(allowance_msgs) + .add_message(provide_liquidity_msg) + .add_event(event)) + } + + fn withdraw_liquidity( + &self, + _deps: Deps, + _env: &Env, + asset: Asset, + mut min_out: AssetList, + ) -> Result { + if let AssetInfoBase::Cw20(token_addr) = &asset.info { + // Liquidity manager requires min_out to contain all assets in the pool + for asset in &self.pool_assets { + if min_out.find(asset).is_none() { + // Add one unit as AssetList does not allow zero amounts (calls self.purge on + // add) + min_out.add(&Asset::new(asset.clone(), Uint128::one()))?; + } + } + + let withdraw_liquidity = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: token_addr.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: self.liquidity_manager.to_string(), + amount: asset.amount, + msg: to_json_binary(&liquidity_manager::Cw20HookMsg::WithdrawLiquidity { + pair_msg: astroport::pair::Cw20HookMsg::WithdrawLiquidity { + // This field is currently not used... + assets: vec![], + }, + min_assets_to_receive: min_out.to_vec().into_elementwise(), + })?, + })?, + funds: vec![], + }); + + let event = Event::new("apollo/cw-dex/withdraw_liquidity") + .add_attribute("pair_addr", &self.pair_addr) + .add_attribute("asset", format!("{:?}", asset)) + .add_attribute("token_amount", asset.amount); + + Ok(Response::new() + .add_message(withdraw_liquidity) + .add_event(event)) + } else { + Err(CwDexError::InvalidInAsset { a: asset }) + } + } + + fn swap( + &self, + _deps: Deps, + env: &Env, + offer_asset: Asset, + ask_asset_info: AssetInfo, + min_out: Uint128, + ) -> Result { + // Setting belief price to the minimium acceptable return and max spread to zero + // simplifies things Astroport will make the best possible swap that + // returns at least `min_out`. + let belief_price = Some(Decimal::from_ratio(offer_asset.amount, min_out)); + let swap_msg = match &offer_asset.info { + AssetInfo::Native(_) => { + let asset = offer_asset.clone().into(); + wasm_execute( + self.pair_addr.to_string(), + &PairExecuteMsg::Swap { + offer_asset: asset, + belief_price, + max_spread: Some(Decimal::zero()), + to: Some(env.contract.address.to_string()), + ask_asset_info: Some(ask_asset_info.to_owned().into()), + }, + vec![offer_asset.clone().try_into()?], + ) + } + AssetInfo::Cw20(addr) => wasm_execute( + addr.to_string(), + &Cw20ExecuteMsg::Send { + contract: self.pair_addr.to_string(), + amount: offer_asset.amount, + msg: to_json_binary(&PairCw20HookMsg::Swap { + belief_price, + max_spread: Some(Decimal::zero()), + to: Some(env.contract.address.to_string()), + ask_asset_info: Some(ask_asset_info.to_owned().into()), + })?, + }, + vec![], + ), + }?; + let event = Event::new("apollo/cw-dex/swap") + .add_attribute("pair_addr", &self.pair_addr) + .add_attribute("ask_asset", format!("{:?}", ask_asset_info)) + .add_attribute("offer_asset", format!("{:?}", offer_asset.info)) + .add_attribute("minimum_out_amount", min_out); + Ok(Response::new().add_message(swap_msg).add_event(event)) + } + + fn get_pool_liquidity(&self, deps: Deps) -> Result { + let resp = self.query_pool_info(&deps.querier)?; + Ok(resp.assets.to_vec().into()) + } + + fn simulate_provide_liquidity( + &self, + deps: Deps, + _env: &Env, + assets: AssetList, + ) -> Result { + let amount: Uint128 = deps.querier.query_wasm_smart( + self.liquidity_manager.to_string(), + &liquidity_manager::QueryMsg::SimulateProvide { + pair_addr: self.pair_addr.to_string(), + pair_msg: astroport::pair::ExecuteMsg::ProvideLiquidity { + assets: assets.into(), + slippage_tolerance: Some(Decimal::from_str(MAX_ALLOWED_SLIPPAGE)?), + auto_stake: Some(false), + receiver: None, + }, + }, + )?; + + let lp_token = Asset { + info: AssetInfo::Cw20(self.lp_token_addr.clone()), + amount, + }; + + Ok(lp_token) + } + + fn simulate_withdraw_liquidity( + &self, + deps: Deps, + lp_token: &Asset, + ) -> Result { + let assets: Vec = deps.querier.query_wasm_smart( + self.liquidity_manager.to_string(), + &liquidity_manager::QueryMsg::SimulateWithdraw { + pair_addr: self.pair_addr.to_string(), + lp_tokens: lp_token.amount, + }, + )?; + + Ok(assets.into()) + } + + fn simulate_swap( + &self, + deps: Deps, + offer_asset: Asset, + ask_asset_info: AssetInfo, + ) -> StdResult { + Ok(deps + .querier + .query::(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.pair_addr.to_string(), + msg: to_json_binary(&PairQueryMsg::Simulation { + offer_asset: offer_asset.into(), + ask_asset_info: Some(ask_asset_info.into()), + })?, + }))? + .return_amount) + } + + fn lp_token(&self) -> AssetInfo { + AssetInfoBase::Cw20(self.lp_token_addr.clone()) + } + + fn pool_assets(&self, _deps: Deps) -> StdResult> { + Ok(self.pool_assets.clone()) + } +} diff --git a/cw-dex-astroport/src/staking.rs b/cw-dex-astroport/src/staking.rs new file mode 100644 index 00000000..f073938e --- /dev/null +++ b/cw-dex-astroport/src/staking.rs @@ -0,0 +1,147 @@ +//! Staking/rewards traits implementations for Astroport + +use apollo_utils::assets::separate_natives_and_cw20s; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + to_json_binary, Addr, CosmosMsg, Deps, Empty, Env, Event, QuerierWrapper, QueryRequest, + Response, Uint128, WasmMsg, WasmQuery, +}; +use cw20::Cw20ExecuteMsg; + +use apollo_cw_asset::AssetList; +use astroport::asset::Asset as AstroAsset; +use astroport_v3::incentives::{ + Cw20Msg as IncentivesCw20Msg, ExecuteMsg as IncentivesExecuteMsg, + QueryMsg as IncentivesQueryMsg, +}; + +use cw_dex::traits::{Rewards, Stake, Staking, Unstake}; +use cw_dex::CwDexError; + +/// Represents staking of tokens on Astroport +#[cw_serde] +pub struct AstroportStaking { + /// The address of the associated LP token contract + pub lp_token_addr: Addr, + /// The address of the astroport incentives contract + pub incentives: Addr, +} + +impl Staking for AstroportStaking {} + +impl Stake for AstroportStaking { + fn stake(&self, _deps: Deps, _env: &Env, amount: Uint128) -> Result { + let stake_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.lp_token_addr.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: self.incentives.to_string(), + amount, + msg: to_json_binary(&IncentivesCw20Msg::Deposit { recipient: None })?, + })?, + funds: vec![], + }); + + let event = Event::new("apollo/cw-dex/stake") + .add_attribute("type", "astroport_staking") + .add_attribute("asset", self.lp_token_addr.to_string()) + .add_attribute("incentives contract address", self.incentives.to_string()); + + Ok(Response::new().add_message(stake_msg).add_event(event)) + } +} + +impl Rewards for AstroportStaking { + fn claim_rewards(&self, deps: Deps, env: &Env) -> Result { + let claimable_rewards: AssetList = + self.query_pending_rewards(&deps.querier, &env.contract.address)?; + + let event = + Event::new("apollo/cw-dex/claim_rewards").add_attribute("type", "astroport_staking"); + + if claimable_rewards.len() == 0 { + return Ok(Response::new().add_event(event)); + } + + let claim_rewards_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesExecuteMsg::ClaimRewards { + lp_tokens: vec![self.lp_token_addr.to_string()], + })?, + funds: vec![], + }); + + let mut res = Response::new().add_message(claim_rewards_msg); + + // Astroport generator only supports CW20 tokens as proxy rewards and wraps + // native tokens in their "CW20 wrapper". We need to unwrap them here. + let (_, cw20s) = separate_natives_and_cw20s(&claimable_rewards); + for cw20 in cw20s { + // Query the cw20s creator to get the address of the wrapper contract + let contract_info = deps.querier.query_wasm_contract_info(&cw20.address)?; + let wrapper_contract = deps.api.addr_validate(&contract_info.creator)?; + + // Query the wrapper contract's cw2 info to check if it is a native token + // wrapper, otherwise skip it + let contract_version = cw2::query_contract_info(&deps.querier, &wrapper_contract).ok(); + match contract_version { + Some(contract_version) => { + if &contract_version.contract != "astroport-native-coin-wrapper" { + continue; + } + } + None => continue, + } + + // Unwrap the native token + let unwrap_msg: CosmosMsg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: cw20.address.to_string(), + msg: to_json_binary(&cw20::Cw20ExecuteMsg::Send { + contract: wrapper_contract.to_string(), + amount: cw20.amount, + msg: to_json_binary(&astroport::native_coin_wrapper::Cw20HookMsg::Unwrap {})?, + })?, + funds: vec![], + }); + res = res.add_message(unwrap_msg); + } + + Ok(res.add_event(event)) + } + + fn query_pending_rewards( + &self, + querier: &QuerierWrapper, + user: &Addr, + ) -> Result { + let pending_rewards: Vec = querier + .query::>(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesQueryMsg::PendingRewards { + lp_token: self.lp_token_addr.to_string(), + user: user.to_string(), + })?, + }))? + .into_iter() + .filter(|asset| !asset.amount.is_zero()) //TODO: Is this necessary? + .collect(); + + Ok(pending_rewards.into()) + } +} + +impl Unstake for AstroportStaking { + fn unstake(&self, _deps: Deps, _env: &Env, amount: Uint128) -> Result { + let unstake_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesExecuteMsg::Withdraw { + lp_token: self.lp_token_addr.to_string(), + amount, + })?, + funds: vec![], + }); + + let event = Event::new("apollo/cw-dex/unstake").add_attribute("type", "astroport_staking"); + + Ok(Response::new().add_message(unstake_msg).add_event(event)) + } +} diff --git a/cw-dex/tests/astroport_tests.rs b/cw-dex-astroport/tests/astroport_tests.rs similarity index 68% rename from cw-dex/tests/astroport_tests.rs rename to cw-dex-astroport/tests/astroport_tests.rs index 77d0f6ad..f1553110 100644 --- a/cw-dex/tests/astroport_tests.rs +++ b/cw-dex-astroport/tests/astroport_tests.rs @@ -1,24 +1,28 @@ -#![cfg(feature = "astroport")] mod tests { use apollo_cw_asset::{Asset, AssetInfo, AssetInfoBase, AssetList}; use apollo_utils::assets::separate_natives_and_cw20s; use apollo_utils::coins::coin_from_str; use apollo_utils::submessages::{find_event, parse_attribute_value}; use astroport::factory::PairType; - use cosmwasm_std::{Addr, Coin, SubMsgResponse, Uint128}; - use cw_dex::Pool; + use astroport_v3::asset::Asset as AstroportAsset; + use cosmwasm_std::{assert_approx_eq, coin, coins, Addr, Coin, SubMsgResponse, Uint128}; + use cw_dex_test_contract::msg::{AstroportExecuteMsg, ExecuteMsg, QueryMsg}; use cw_dex_test_helpers::astroport::setup_pool_and_test_contract; use cw_dex_test_helpers::{cw20_balance_query, cw20_transfer, query_asset_balance}; + use cw_it::astroport::utils::AstroportContracts; use cw_it::helpers::Unwrap; use cw_it::multi_test::MultiTestRunner; use cw_it::test_tube::cosmrs::proto::cosmwasm::wasm::v1::MsgExecuteContractResponse; use cw_it::test_tube::{ Account, ExecuteResponse, Module, Runner, RunnerResult, SigningAccount, Wasm, }; + use cw_it::traits::CwItRunner; use cw_it::{OwnedTestRunner, TestRunner}; use test_case::test_case; + use cw_dex_astroport::AstroportPool; + #[cfg(feature = "osmosis-test-tube")] use cw_it::osmosis_test_tube::OsmosisTestApp; @@ -33,11 +37,18 @@ mod tests { const TEST_CONTRACT_WASM_FILE_PATH: &str = "../target/wasm32-unknown-unknown/release/astroport_test_contract.wasm"; - fn setup_pool_and_contract<'a>( + fn setup_pool_and_testing_contract<'a>( runner: &'a TestRunner<'a>, pool_type: PairType, initial_liquidity: Vec<(&str, u64)>, - ) -> RunnerResult<(Vec, String, String, String, AssetList)> { + ) -> RunnerResult<( + Vec, + String, + String, + String, + AssetList, + AstroportContracts, + )> { setup_pool_and_test_contract( runner, pool_type, @@ -58,8 +69,8 @@ mod tests { pub fn test_provide_liquidity(pool_type: PairType, initial_liquidity: Vec<(&str, u64)>) { let owned_runner = get_test_runner(); let runner = owned_runner.as_ref(); - let (accs, lp_token_addr, _pair_addr, contract_addr, asset_list) = - setup_pool_and_contract(&runner, pool_type.clone(), initial_liquidity).unwrap(); + let (accs, lp_token_addr, _pair_addr, contract_addr, asset_list, _) = + setup_pool_and_testing_contract(&runner, pool_type.clone(), initial_liquidity).unwrap(); let admin = &accs[0]; let wasm = Wasm::new(&runner); @@ -141,8 +152,8 @@ mod tests { fn test_withdraw_liquidity(pool_type: PairType, initial_liquidity: Vec<(&str, u64)>) { let owned_runner = get_test_runner(); let runner = owned_runner.as_ref(); - let (accs, lp_token_addr, _pair_addr, contract_addr, asset_list) = - setup_pool_and_contract(&runner, pool_type, initial_liquidity).unwrap(); + let (accs, lp_token_addr, _pair_addr, contract_addr, asset_list, _) = + setup_pool_and_testing_contract(&runner, pool_type, initial_liquidity).unwrap(); let admin = &accs[0]; let wasm = Wasm::new(&runner); @@ -255,8 +266,8 @@ mod tests { ) -> RunnerResult<()> { let owned_runner = get_test_runner(); let runner = owned_runner.as_ref(); - let (accs, lp_token_addr, _pair_addr, contract_addr, _asset_list) = - setup_pool_and_contract(&runner, pool_type, initial_liquidity).unwrap(); + let (accs, lp_token_addr, _pair_addr, contract_addr, _asset_list, _) = + setup_pool_and_testing_contract(&runner, pool_type, initial_liquidity).unwrap(); let admin = &accs[0]; @@ -342,8 +353,8 @@ mod tests { ) { let owned_runner = get_test_runner(); let runner = owned_runner.as_ref(); - let (accs, _lp_token_addr, _pair_addr, contract_addr, asset_list) = - setup_pool_and_contract(&runner, pool_type, initial_liquidity).unwrap(); + let (accs, _lp_token_addr, _pair_addr, contract_addr, asset_list, _) = + setup_pool_and_testing_contract(&runner, pool_type, initial_liquidity).unwrap(); let admin = &accs[0]; let wasm = Wasm::new(&runner); @@ -405,37 +416,244 @@ mod tests { assert_eq!(offer_balance, Uint128::zero()); } - #[test] - fn test_get_pool_for_lp_token() { + #[test_case(vec![(coin(2_000_000_000, "uluna"), 1)], vec![]; "one native incentive one period")] + #[test_case(vec![(coin(4_000_000_000, "uluna"), 2)], vec![]; "one native incentive two periods")] + #[test_case(vec![(coin(4_000_000_000, "uluna"), 2), (coin(2_000_000_000, "untrn"), 1)], vec![]; "two native incentive different periods")] + #[test_case(vec![(coin(4_000_000_000, "uluna"), 2), (coin(2_000_000_000, "untrn"), 1)], vec![(4_000_000_000u128.into(), 2)]; "two native incentive different periods one cw20 incentive")] + fn test_claim_rewards( + native_incentives: Vec<(Coin, u64)>, + cw20_incentives: Vec<(Uint128, u64)>, + ) -> RunnerResult<()> { + let pool_type = PairType::Xyk {}; + let initial_liquidity = vec![("uluna", 1_000_000), ("astro", 1_000_000)]; + let owned_runner = get_test_runner(); let runner = owned_runner.as_ref(); - let (_accs, lp_token_addr, pair_addr, contract_addr, asset_list) = setup_pool_and_contract( + let ( + accs, + lp_token_addr, + _pair_addr, + testing_contract_addr, + _asset_list, + astroport_contracts, + ) = setup_pool_and_testing_contract(&runner, pool_type, initial_liquidity).unwrap(); + + let admin = &accs[0]; + + // Increase time to current time. For some reason the start time of the + // incenitve epochs is hard coded in the astroport incentives contract + // and the logic doesn't work for earlier timestamps + let block_time = runner.query_block_time_nanos() / 1_000_000_000; + let current_time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + runner + .increase_time((current_time.saturating_sub(block_time)) as u64) + .unwrap(); + + // Setup wasm runner + let wasm = Wasm::new(&runner); + + // Initialize account with balances of all native incentives + let incentives_provider = runner + .init_account( + &native_incentives + .clone() + .into_iter() + .map(|(coin, _)| coin) + .chain(coins(10000000000, "uosmo")) // for gas + .collect::>(), + ) + .unwrap(); + + // Convert native incentives to AstroportAssets + let mut incentives: Vec<(AstroportAsset, u64)> = native_incentives + .clone() + .into_iter() + .map(|(coin, duration)| (coin.into(), duration)) + .collect(); + + // Create Cw20 tokens for each Cw20 incentive, mint incentive amount to + // incentives_provider and add to incentives + let cw20_code_id = astroport_contracts.astro_token.code_id; + for (i, (amount, duration)) in cw20_incentives.iter().enumerate() { + // Instantiate Cw20 token + let cw20_addr = wasm + .instantiate( + cw20_code_id, + &cw20_base::msg::InstantiateMsg { + name: format!("cw20_incentive_{}", i), + symbol: "incentive".to_string(), + decimals: 6, + initial_balances: vec![cw20::Cw20Coin { + address: incentives_provider.address(), + amount: *amount, + }], + mint: None, + marketing: None, + }, + Some(&admin.address()), + Some("incentive"), + &[], + admin, + ) + .unwrap() + .data + .address; + + // Add Cw20 incentive to incentives + incentives.push(( + AstroportAsset::cw20(Addr::unchecked(cw20_addr), *amount), + *duration, + )); + } + + // Setup incentives for the pool + for (incentive, periods) in incentives.clone() { + // Increase allowance for cw20 incentives and construct funds + let funds = match incentive.info.clone() { + astroport_v3::asset::AssetInfo::Token { contract_addr } => { + // Increase allowance for incentives contract + wasm.execute( + contract_addr.as_str(), + &cw20::Cw20ExecuteMsg::IncreaseAllowance { + spender: astroport_contracts.incentives.address.clone(), + amount: incentive.amount, + expires: None, + }, + &[], + &incentives_provider, + ) + .unwrap(); + vec![] + } + astroport_v3::asset::AssetInfo::NativeToken { denom } => { + vec![coin(incentive.amount.u128(), &denom)] + } + }; + wasm.execute( + &astroport_contracts.incentives.address, + &astroport_v3::incentives::ExecuteMsg::Incentivize { + lp_token: lp_token_addr.clone(), + schedule: astroport_v3::incentives::InputSchedule { + reward: incentive, + duration_periods: periods, + }, + }, + &funds, + &incentives_provider, + ) + .unwrap(); + } + + // Query LP token balance + let lp_token_balance = + cw20_balance_query(&runner, lp_token_addr.clone(), admin.address()).unwrap(); + + // Send LP tokens to the test contract + cw20_transfer( + &runner, + lp_token_addr.clone(), + testing_contract_addr.clone(), + lp_token_balance, + admin, + ) + .unwrap(); + + // Stake LP tokens + let _events = stake_all_lp_tokens( &runner, - PairType::Xyk {}, - vec![("uluna", 1_000_000), ("uatom", 1_000_000)], + testing_contract_addr.clone(), + lp_token_addr.clone(), + admin, + ) + .events; + + // Increase time by 1 week + runner.increase_time(60 * 60 * 24).unwrap(); + + // Query incentives contract for admin users pending rewards + let pending_rewards: Vec = wasm + .query( + &astroport_contracts.incentives.address, + &astroport_v3::incentives::QueryMsg::PendingRewards { + lp_token: lp_token_addr.clone(), + user: testing_contract_addr.clone(), + }, + ) + .unwrap(); + + // Query pending rewards through CwDex testing contract + let cw_dex_pending_rewards: AssetList = wasm + .query( + &testing_contract_addr, + &cw_dex_test_contract::msg::QueryMsg::PendingRewards {}, + ) + .unwrap(); + + // Assert that both pending rewards queries return the same result + for asset in pending_rewards.clone() { + // Convert astroport asset info to asset info + let asset_info = match asset.info { + astroport_v3::asset::AssetInfo::Token { contract_addr } => { + AssetInfo::Cw20(contract_addr) + } + astroport_v3::asset::AssetInfo::NativeToken { denom } => AssetInfo::Native(denom), + }; + + let amount = cw_dex_pending_rewards.find(&asset_info).unwrap().amount; + + assert_eq!(amount, asset.amount); + } + + // Claim rewards + wasm.execute( + &testing_contract_addr, + &cw_dex_test_contract::msg::AstroportExecuteMsg::ClaimRewards {}, + &[], + admin, ) .unwrap(); + // Assert that testing contract has correct asset balances + for reward in cw_dex_pending_rewards.to_vec() { + let asset_balance = query_asset_balance(&runner, &reward.info, &testing_contract_addr); + assert_approx_eq!(asset_balance, reward.amount, "0.0001"); // TODO: Why is there a diff here? + } + + Ok(()) + } + + #[test] + fn test_get_pool_for_lp_token() { + let owned_runner = get_test_runner(); + let runner = owned_runner.as_ref(); + let (_accs, lp_token_addr, pair_addr, contract_addr, asset_list, _) = + setup_pool_and_testing_contract( + &runner, + PairType::Xyk {}, + vec![("uluna", 1_000_000), ("uatom", 1_000_000)], + ) + .unwrap(); + let wasm = Wasm::new(&runner); let query = QueryMsg::GetPoolForLpToken { lp_token: AssetInfo::Cw20(Addr::unchecked(lp_token_addr.clone())), }; - let pool = wasm.query::<_, Pool>(&contract_addr, &query).unwrap(); - - match pool { - Pool::Astroport(pool) => { - assert_eq!(pool.lp_token_addr, Addr::unchecked(lp_token_addr)); - assert_eq!(pool.pair_addr, Addr::unchecked(pair_addr)); - assert_eq!( - pool.pool_assets, - asset_list - .into_iter() - .map(|x| x.info.clone()) - .collect::>() - ); - } - _ => panic!("Wrong pool type"), - } + let pool = wasm + .query::<_, AstroportPool>(&contract_addr, &query) + .unwrap(); + + assert_eq!(pool.lp_token_addr, Addr::unchecked(lp_token_addr)); + assert_eq!(pool.pair_addr, Addr::unchecked(pair_addr)); + assert_eq!( + pool.pool_assets, + asset_list + .into_iter() + .map(|x| x.info.clone()) + .collect::>() + ); } } diff --git a/cw-dex-osmosis/Cargo.toml b/cw-dex-osmosis/Cargo.toml new file mode 100644 index 00000000..6625dec6 --- /dev/null +++ b/cw-dex-osmosis/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "cw-dex-osmosis" +authors = ["Apollo Devs"] +description = "Implementation of the cw-dex API for the Osmosis AMM" +edition = "2021" +license = "MPL-2.0" +repository = "https://github.com/apollodao/cw-dex" +version = "0.1.0" +readme = "README.md" + +[features] +default = [] +osmosis-test-tube = ["cw-it/osmosis-test-tube", "cw-dex-test-helpers/osmosis-test-tube"] +# backtraces = ["cosmwasm-std/backtraces", "osmosis-std/backtraces"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +cw-dex = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +apollo-cw-asset = { workspace = true } +cw-utils = { workspace = true } +apollo-utils = { workspace = true } +osmosis-std = { workspace = true } + + +[dev-dependencies] +cw-it = { workspace = true } +test-case = { workspace = true } +cw-dex-test-contract = { workspace = true } +cw-dex-test-helpers = { workspace = true, features = ["osmosis"] } +proptest = { workspace = true } +cw20-base = { workspace = true } +cw20 = { workspace = true } diff --git a/cw-dex-osmosis/src/helpers.rs b/cw-dex-osmosis/src/helpers.rs new file mode 100644 index 00000000..b1c031ea --- /dev/null +++ b/cw-dex-osmosis/src/helpers.rs @@ -0,0 +1,14 @@ +use std::time::Duration; + +pub(crate) trait ToProtobufDuration { + fn to_protobuf_duration(&self) -> osmosis_std::shim::Duration; +} + +impl ToProtobufDuration for Duration { + fn to_protobuf_duration(&self) -> osmosis_std::shim::Duration { + osmosis_std::shim::Duration { + seconds: self.as_secs() as i64, + nanos: self.subsec_nanos() as i32, + } + } +} diff --git a/cw-dex-osmosis/src/lib.rs b/cw-dex-osmosis/src/lib.rs new file mode 100644 index 00000000..2013d312 --- /dev/null +++ b/cw-dex-osmosis/src/lib.rs @@ -0,0 +1,9 @@ +//! Contains cw-dex Pool and Staking implementations for Osmosis + +mod helpers; +mod pool; +mod staking; + +pub use osmosis_std; +pub use pool::*; +pub use staking::*; diff --git a/cw-dex-osmosis/src/pool.rs b/cw-dex-osmosis/src/pool.rs new file mode 100644 index 00000000..e481917c --- /dev/null +++ b/cw-dex-osmosis/src/pool.rs @@ -0,0 +1,350 @@ +//! Pool trait implementation for Osmosis + +use std::ops::Deref; +use std::str::FromStr; + +use apollo_utils::assets::{ + assert_native_asset_info, assert_native_coin, assert_only_native_coins, merge_assets, +}; +use apollo_utils::iterators::{IntoElementwise, TryIntoElementwise}; +use osmosis_std::types::osmosis::gamm::v1beta1::{ + GammQuerier, MsgExitPool, MsgJoinPool, MsgJoinSwapExternAmountIn, MsgSwapExactAmountIn, +}; + +use apollo_cw_asset::{Asset, AssetInfo, AssetList}; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + Coin, CosmosMsg, Deps, Env, Event, QuerierWrapper, Response, StdResult, Uint128, +}; +use osmosis_std::types::osmosis::poolmanager::v1beta1::{ + PoolmanagerQuerier, SwapAmountInRoute, TotalPoolLiquidityRequest, +}; + +use cw_dex::traits::Pool; +use cw_dex::CwDexError; + +/// Struct for interacting with Osmosis v1beta1 balancer pools. If `pool_id` +/// maps to another type of pool this will fail. +#[cw_serde] +#[derive(Copy)] +pub struct OsmosisPool { + /// The pool id of the pool to interact with + pool_id: u64, +} + +impl OsmosisPool { + /// Creates a new `OsmosisPool` instance with the given `pool_id` and + /// validates that the pool exists. + pub fn new(pool_id: u64, deps: Deps) -> StdResult { + let pool = Self { pool_id }; + // If this query succeeds then the pool exists + pool.get_pool_liquidity(deps)?; + Ok(pool) + } + + /// Creates an unchecked pool for use in testing. + pub fn unchecked(pool_id: u64) -> Self { + Self { pool_id } + } + + /// Returns the matching pool given a LP token. + /// + /// Arguments: + /// - `lp_token`: Said LP token + pub fn get_pool_for_lp_token(deps: Deps, lp_token: &AssetInfo) -> Result { + match lp_token { + AssetInfo::Native(lp_token_denom) => { + if !lp_token_denom.starts_with("gamm/pool/") { + return Err(CwDexError::NotLpToken {}); + } + + let pool_id_str = lp_token_denom + .strip_prefix("gamm/pool/") + .ok_or(CwDexError::NotLpToken {})?; + + let pool_id = u64::from_str(pool_id_str).map_err(|_| CwDexError::NotLpToken {})?; + + Ok(OsmosisPool::new(pool_id, deps)?) + } + _ => Err(CwDexError::NotLpToken {}), + } + } + + /// Returns the pool id of the pool + pub fn pool_id(&self) -> u64 { + self.pool_id + } + + /// Simulates a single sided join and returns `Uint128` amount of LP tokens + /// returned. A single sided join will use all of the provided asset. + pub fn simulate_single_sided_join( + &self, + querier: &QuerierWrapper, + asset: &Asset, + ) -> StdResult { + let querier = GammQuerier::new(querier); + let share_out_amount = Uint128::from_str( + &querier + .calc_join_pool_shares(self.pool_id, vec![assert_native_coin(asset)?.into()])? + .share_out_amount, + )?; + Ok(share_out_amount) + } + + /// Simulates a liquidity provision with all of the assets of the pool. + /// Returns `(Uint128, AssetList)` amount of LP tokens returned and the + /// tokens used to join the pool. + pub fn simulate_noswap_join( + &self, + querier: &QuerierWrapper, + assets: &AssetList, + ) -> StdResult<(Uint128, AssetList)> { + let querier = GammQuerier::new(querier); + let response = &querier.calc_join_pool_no_swap_shares( + self.pool_id, + assert_only_native_coins(assets)?.into_elementwise(), + )?; + let lp_tokens_returned = Uint128::from_str(&response.shares_out)?; + let tokens_used: Vec = response + .tokens_out + .iter() + .map(|x| { + Ok(Coin { + denom: x.denom.clone(), + amount: Uint128::from_str(&x.amount)?, + }) + }) + .collect::>()?; + + Ok((lp_tokens_returned, AssetList::from(tokens_used))) + } +} + +impl Pool for OsmosisPool { + fn provide_liquidity( + &self, + deps: Deps, + env: &Env, + assets: AssetList, + min_out: Uint128, + ) -> Result { + let mut assets = assets; + + // Remove all zero amount Coins, merge duplicates and assert that all assets are + // native. + let mut assets = assert_only_native_coins(&merge_assets(assets.purge().deref())?)?; + + let expected_shares = self + .simulate_provide_liquidity(deps, env, assets.to_owned().into())? + .amount; + + // Assert slippage tolerance + if min_out > expected_shares { + return Err(CwDexError::MinOutNotReceived { + min_out, + received: expected_shares, + }); + } + + // sort assets + assets.sort_by(|a, b| a.denom.to_string().cmp(&b.denom)); + + let join_pool: CosmosMsg = if assets.len() == 1 { + MsgJoinSwapExternAmountIn { + sender: env.contract.address.to_string(), + pool_id: self.pool_id, + share_out_min_amount: expected_shares.to_string(), + token_in: Some(assets[0].clone().into()), + } + .into() + } else { + MsgJoinPool { + sender: env.contract.address.to_string(), + pool_id: self.pool_id, + share_out_amount: expected_shares.to_string(), + token_in_maxs: assets.into_elementwise(), + } + .into() + }; + + let event = Event::new("apollo/cw-dex/provide_liquidity") + .add_attribute("pool_id", self.pool_id.to_string()) + .add_attribute("min_out", min_out) + .add_attribute("expected_shares", expected_shares); + + Ok(Response::new().add_message(join_pool).add_event(event)) + } + + fn withdraw_liquidity( + &self, + _deps: Deps, + env: &Env, + lp_token: Asset, + min_out: AssetList, + ) -> Result { + let min_out_coins = assert_only_native_coins(&min_out)?.try_into_elementwise()?; + + let exit_msg = MsgExitPool { + sender: env.contract.address.to_string(), + pool_id: self.pool_id, + share_in_amount: lp_token.amount.to_string(), + token_out_mins: min_out_coins, + }; + + let mut event = Event::new("apollo/cw-dex/withdraw_liquidity") + .add_attribute("pool_id", self.pool_id.to_string()) + .add_attribute("shares_in", lp_token.to_string()); + + // We're not allowed to add empty values as attributes. + if !min_out.len() == 0 { + event = event.add_attribute("min_out", min_out.to_string()); + } + + Ok(Response::new().add_message(exit_msg).add_event(event)) + } + + fn swap( + &self, + _deps: Deps, + env: &Env, + offer_asset: Asset, + ask_asset_info: AssetInfo, + min_out: Uint128, + ) -> Result { + let offer = assert_native_coin(&offer_asset)?; + let ask_denom = assert_native_asset_info(&ask_asset_info)?; + + // Min out must be greater than 0 for osmosis. + let min_out = if min_out == Uint128::zero() { + Uint128::one() + } else { + min_out + }; + + let swap_msg = MsgSwapExactAmountIn { + sender: env.contract.address.to_string(), + routes: vec![SwapAmountInRoute { + pool_id: self.pool_id, + token_out_denom: ask_denom.clone(), + }], + token_in: Some(offer.clone().into()), + token_out_min_amount: min_out.to_string(), + }; + + let event = Event::new("apollo/cw-dex/swap") + .add_attribute("pool_id", self.pool_id.to_string()) + .add_attribute("offer", offer.to_string()) + .add_attribute("ask", ask_denom) + .add_attribute("token_out_min_amount", min_out); + + Ok(Response::new().add_message(swap_msg).add_event(event)) + } + + fn get_pool_liquidity(&self, deps: Deps) -> Result { + let pool_assets = TotalPoolLiquidityRequest { + pool_id: self.pool_id, + } + .query(&deps.querier)?; + + let asset_list: AssetList = pool_assets + .liquidity + .into_iter() + .map(|coin| { + Ok(Asset { + info: AssetInfo::Native(coin.denom), + amount: Uint128::from_str(&coin.amount)?, + }) + }) + .collect::>>()? + .into(); + + Ok(asset_list) + } + + fn simulate_provide_liquidity( + &self, + deps: Deps, + _env: &Env, + assets: AssetList, + ) -> Result { + let shares_out_amount: Uint128; + if assets.len() == 1 { + shares_out_amount = + self.simulate_single_sided_join(&deps.querier, &assets.to_vec()[0])?; + } else { + (shares_out_amount, _) = self.simulate_noswap_join(&deps.querier, &assets)?; + } + + Ok(Asset::new(self.lp_token(), shares_out_amount)) + } + + fn simulate_withdraw_liquidity( + &self, + deps: Deps, + lp_token: &Asset, + ) -> Result { + let querier = GammQuerier::new(&deps.querier); + let lp_denom = self.lp_token(); + + if lp_denom != lp_token.info { + return Err(CwDexError::InvalidLpToken {}); + } + + let tokens_out: Vec = querier + .calc_exit_pool_coins_from_shares(self.pool_id, lp_token.amount.to_string())? + .tokens_out + .iter() + .map(|c| { + Ok(Coin { + denom: c.denom.clone(), + amount: Uint128::from_str(&c.amount)?, + }) + }) + .collect::>()?; + + Ok(tokens_out.into()) + } + + fn simulate_swap( + &self, + deps: Deps, + offer: Asset, + ask_asset_info: AssetInfo, + ) -> StdResult { + let offer: Coin = offer.try_into()?; + let swap_response = PoolmanagerQuerier::new(&deps.querier).estimate_swap_exact_amount_in( + self.pool_id, + offer.to_string(), + vec![SwapAmountInRoute { + pool_id: self.pool_id, + token_out_denom: assert_native_asset_info(&ask_asset_info)?, + }], + )?; + Uint128::from_str(swap_response.token_out_amount.as_str()) + } + + fn lp_token(&self) -> AssetInfo { + AssetInfo::Native(format!("gamm/pool/{}", self.pool_id)) + } +} + +#[cfg(test)] +mod tests { + use apollo_cw_asset::AssetInfo; + + use cw_dex::traits::Pool; + + use super::OsmosisPool; + + #[test] + fn test_lp_token() { + let pool = OsmosisPool::unchecked(1337u64); + + let lp_token = pool.lp_token(); + + match lp_token { + AssetInfo::Native(denom) => assert_eq!(denom, format!("gamm/pool/{}", 1337u64)), + AssetInfo::Cw20(_) => panic!("Unexpected cw20 token"), + } + } +} diff --git a/cw-dex-osmosis/src/staking.rs b/cw-dex-osmosis/src/staking.rs new file mode 100644 index 00000000..9442a96b --- /dev/null +++ b/cw-dex-osmosis/src/staking.rs @@ -0,0 +1,325 @@ +//! Staking/rewards traits implementations for Osmosis + +use apollo_cw_asset::AssetList; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + Addr, Coin, Deps, Env, Event, QuerierWrapper, ReplyOn, Response, StdError, StdResult, SubMsg, + Uint128, +}; +use cw_utils::Duration as CwDuration; +use osmosis_std::types::osmosis::lockup::{MsgBeginUnlocking, MsgForceUnlock, MsgLockTokens}; +use osmosis_std::types::osmosis::superfluid::{ + MsgLockAndSuperfluidDelegate, MsgSuperfluidUnbondLock, MsgSuperfluidUndelegate, +}; +use std::time::Duration; + +use cw_dex::traits::{ForceUnlock, LockedStaking, Rewards, Stake, Unlock}; +use cw_dex::CwDexError; + +use super::helpers::ToProtobufDuration; + +/// Implementation of locked staking on osmosis. Using the Staking trait. +/// `lockup_duration` is the duration of the lockup period in nano seconds. +#[cw_serde] +pub struct OsmosisStaking { + /// Lockup duration in nano seconds. Allowed values 1 day, 1 week or 2 + /// weeks. + pub lockup_duration: Duration, + /// ID for the lockup record + pub lock_id: Option, + /// Denomination of the associated LP token + pub lp_token_denom: String, +} + +impl OsmosisStaking { + /// Creates a new OsmosisStaking instance with lock up duration set to + /// `lockup_duration`. + /// + /// Arguments: + /// - `lockup_duration` is the duration of the lockup period in seconds. + /// + /// Returns an error if `lockup_duration` is not one of the allowed values, + /// 86400, 604800 or 1209600, representing 1 day, 1 week or 2 weeks + /// respectively. + pub fn new( + lockup_duration: u64, + lock_id: Option, + lp_token_denom: String, + ) -> StdResult { + if !([86400u64, 604800u64, 1209600u64].contains(&lockup_duration)) { + return Err(StdError::generic_err( + "osmosis error: invalid lockup duration", + )); + } + Ok(Self { + lockup_duration: Duration::from_secs(lockup_duration), + lock_id, + lp_token_denom, + }) + } +} + +/// Reply ID for locking tokens +pub const OSMOSIS_LOCK_TOKENS_REPLY_ID: u64 = 123; +/// Reply ID for unlocking tokens +pub const OSMOSIS_UNLOCK_TOKENS_REPLY_ID: u64 = 124; + +impl Rewards for OsmosisStaking { + fn claim_rewards(&self, _deps: Deps, _env: &Env) -> Result { + // Rewards are automatically distributed to stakers every epoch. + let event = + Event::new("apollo/cw-dex/claim_rewards").add_attribute("type", "osmosis_staking"); + Ok(Response::new().add_event(event)) + } + + fn query_pending_rewards( + &self, + _querier: &QuerierWrapper, + _user: &Addr, + ) -> Result { + // Rewards are automatically distributed to stakers every epoch. + // There is no currently no way to query how many have accumulated since + // last epoch. + Ok(AssetList::new()) + } +} + +impl Stake for OsmosisStaking { + fn stake(&self, _deps: Deps, env: &Env, amount: Uint128) -> Result { + let asset = Coin::new(amount.u128(), self.lp_token_denom.clone()); + + let stake_msg = MsgLockTokens { + owner: env.contract.address.to_string(), + duration: Some(self.lockup_duration.to_protobuf_duration()), + coins: vec![asset.clone().into()], + }; + + let event = Event::new("apollo/cw-dex/stake") + .add_attribute("type", "osmosis_staking") + .add_attribute("asset", asset.to_string()) + .add_attribute( + "lockup_duration_secs", + self.lockup_duration.as_secs().to_string(), + ); + + Ok(Response::new() + .add_submessage(SubMsg { + id: OSMOSIS_LOCK_TOKENS_REPLY_ID, + msg: stake_msg.into(), + gas_limit: None, + reply_on: ReplyOn::Success, + }) + .add_event(event)) + } +} + +impl Unlock for OsmosisStaking { + fn unlock(&self, _deps: Deps, env: &Env, amount: Uint128) -> Result { + let asset = Coin::new(amount.u128(), self.lp_token_denom.clone()); + + let id = self + .lock_id + .ok_or_else(|| StdError::generic_err("osmosis error: lock id not set"))?; + + let unstake_msg = MsgBeginUnlocking { + owner: env.contract.address.to_string(), + id, + coins: vec![asset.clone().into()], + }; + + let event = Event::new("apollo/cw-dex/unstake") + .add_attribute("type", "osmosis_staking") + .add_attribute("asset", asset.to_string()) + .add_attribute( + "lockup_duration_secs", + self.lockup_duration.as_secs().to_string(), + ) + .add_attribute("lock_id", id.to_string()); + + Ok(Response::new() + .add_submessage(SubMsg { + id: OSMOSIS_UNLOCK_TOKENS_REPLY_ID, + msg: unstake_msg.into(), + gas_limit: None, + reply_on: ReplyOn::Success, + }) + .add_event(event)) + } + + fn withdraw_unlocked( + &self, + _deps: Deps, + _env: &Env, + _amount: Uint128, + ) -> Result { + // Osmosis automatically sends the unlocked tokens after the lockup duration + let event = + Event::new("apollo/cw-dex/withdraw_unlocked").add_attribute("type", "osmosis_staking"); + Ok(Response::new().add_event(event)) + } +} + +impl LockedStaking for OsmosisStaking { + fn get_lockup_duration(&self, _deps: Deps) -> Result { + Ok(CwDuration::Time(self.lockup_duration.as_secs())) + } +} + +impl ForceUnlock for OsmosisStaking { + fn force_unlock( + &self, + _deps: Deps, + env: &Env, + lockup_id: Option, + amount: Uint128, + ) -> Result { + let lockup_id = match lockup_id { + Some(id) => Ok(id), + None => self + .lock_id + .ok_or_else(|| StdError::generic_err("osmosis error: lock id not set")), + }?; + + let coin_to_unlock = Coin::new(amount.u128(), self.lp_token_denom.clone()); + + let force_unlock_msg = MsgForceUnlock { + owner: env.contract.address.to_string(), + id: lockup_id, + coins: vec![coin_to_unlock.into()], + }; + + let event = Event::new("apollo/cw-dex/force-unlock") + .add_attribute("type", "osmosis_staking") + .add_attribute("amount", amount) + .add_attribute("lockup_id", lockup_id.to_string()); + + Ok(Response::new() + .add_message(force_unlock_msg) + .add_event(event)) + } +} + +/// Implementation of superfluid staking for osmosis. +#[cw_serde] +pub struct OsmosisSuperfluidStaking { + /// Address of the validator to delegate to. + pub validator_address: Addr, + /// ID of the lockup record. + pub lock_id: Option, + /// Denomination of the associated LP token. + pub lp_token_denom: String, +} + +const TWO_WEEKS_IN_SECS: u64 = 14 * 24 * 60 * 60; + +impl OsmosisSuperfluidStaking { + /// Creates a new instance of `OsmosisSuperfluidStaking`. + /// + /// Arguments: + /// - `validator_address`: Address of the associated validator + /// - `lock_id`: ID of the lockup record + /// - `lp_token_denom`: LP token denomination + pub fn new( + validator_address: Addr, + lock_id: Option, + lp_token_denom: String, + ) -> StdResult { + Ok(Self { + validator_address, + lock_id, + lp_token_denom, + }) + } +} + +impl Rewards for OsmosisSuperfluidStaking { + fn claim_rewards(&self, _deps: Deps, _env: &Env) -> Result { + // Rewards are automatically distributed to stakers every epoch. + let event = Event::new("apollo/cw-dex/claim_rewards") + .add_attribute("type", "osmosis_superfluid_staking"); + Ok(Response::new().add_event(event)) + } + + fn query_pending_rewards( + &self, + _querier: &QuerierWrapper, + _user: &Addr, + ) -> Result { + // Rewards are automatically distributed to stakers every epoch. + // There is no currently no way to query how many have accumulated since + // last epoch. + Ok(AssetList::new()) + } +} + +impl Stake for OsmosisSuperfluidStaking { + fn stake(&self, _deps: Deps, env: &Env, amount: Uint128) -> Result { + let asset = Coin::new(amount.u128(), self.lp_token_denom.clone()); + + let stake_msg = MsgLockAndSuperfluidDelegate { + sender: env.contract.address.to_string(), + coins: vec![asset.clone().into()], + val_addr: self.validator_address.to_string(), + }; + + let event = Event::new("apollo/cw-dex/stake") + .add_attribute("type", "osmosis_superfluid_staking") + .add_attribute("asset", asset.to_string()) + .add_attribute("validator_address", self.validator_address.to_string()); + + Ok(Response::new() + .add_submessage(SubMsg { + id: OSMOSIS_LOCK_TOKENS_REPLY_ID, + msg: stake_msg.into(), + gas_limit: None, + reply_on: ReplyOn::Success, + }) + .add_event(event)) + } +} + +impl Unlock for OsmosisSuperfluidStaking { + fn unlock(&self, _deps: Deps, env: &Env, _amount: Uint128) -> Result { + let lock_id = self + .lock_id + .ok_or_else(|| StdError::generic_err("osmosis error: lock id not set"))?; + + let undelegate_msg = MsgSuperfluidUndelegate { + sender: env.contract.address.to_string(), + lock_id, + }; + let unstake_msg = MsgSuperfluidUnbondLock { + sender: env.contract.address.to_string(), + lock_id, + }; + + let event = Event::new("apollo/cw-dex/unstake") + .add_attribute("type", "osmosis_superfluid_staking") + .add_attribute("validator_address", self.validator_address.to_string()) + .add_attribute("lock_id", lock_id.to_string()); + + Ok(Response::new() + .add_message(undelegate_msg) + .add_message(unstake_msg) + .add_event(event)) + } + + fn withdraw_unlocked( + &self, + _deps: Deps, + _env: &Env, + _amount: Uint128, + ) -> Result { + // Osmosis automatically sends the unlocked tokens after the lockup duration + let event = Event::new("apollo/cw-dex/withdraw_unlocked") + .add_attribute("type", "osmosis_superfluid_staking"); + Ok(Response::new().add_event(event)) + } +} + +impl LockedStaking for OsmosisSuperfluidStaking { + fn get_lockup_duration(&self, _deps: Deps) -> Result { + // Lockup time for superfluid staking is always 14 days. + Ok(CwDuration::Time(TWO_WEEKS_IN_SECS)) + } +} diff --git a/cw-dex/tests/osmosis_proptests.proptest-regressions b/cw-dex-osmosis/tests/osmosis_proptests.proptest-regressions similarity index 100% rename from cw-dex/tests/osmosis_proptests.proptest-regressions rename to cw-dex-osmosis/tests/osmosis_proptests.proptest-regressions diff --git a/cw-dex/tests/osmosis_proptests.rs b/cw-dex-osmosis/tests/osmosis_proptests.rs similarity index 100% rename from cw-dex/tests/osmosis_proptests.rs rename to cw-dex-osmosis/tests/osmosis_proptests.rs diff --git a/cw-dex/tests/osmosis_tests.rs b/cw-dex-osmosis/tests/osmosis_tests.rs similarity index 100% rename from cw-dex/tests/osmosis_tests.rs rename to cw-dex-osmosis/tests/osmosis_tests.rs diff --git a/cw-dex/Cargo.toml b/cw-dex/Cargo.toml index 7568a425..a445c185 100644 --- a/cw-dex/Cargo.toml +++ b/cw-dex/Cargo.toml @@ -5,14 +5,14 @@ edition = "2021" license = "MPL-2.0" name = "cw-dex" repository = "https://github.com/apollodao/cw-dex" -version = "0.5.1" +version = "0.5.2" readme = "README.md" [features] default = [] -osmosis = ["osmosis-std", "osmosis-test-tube"] -osmosis-test-tube = ["cw-it/osmosis-test-tube"] -astroport = ["dep:astroport", "apollo-cw-asset/astroport", "dep:cw2", "cw-it/astroport", "cw-it/astroport-multi-test"] +osmosis = ["osmosis-std", "osmosis-test-tube", "cw-it/osmosis", "cw-dex-test-helpers/osmosis"] +osmosis-test-tube = ["cw-it/osmosis-test-tube", "cw-dex-test-helpers/osmosis-test-tube"] +astroport = ["dep:astroport", "dep:astroport_v3", "apollo-cw-asset/astroport", "dep:cw2", "cw-it/astroport", "cw-it/astroport-multi-test", "cw-dex-test-helpers/astroport"] # backtraces = ["cosmwasm-std/backtraces", "osmosis-std/backtraces"] [package.metadata.docs.rs] @@ -29,16 +29,18 @@ cw20 = { workspace = true } apollo-utils = { workspace = true } # Osmosis -osmosis-std = { workspace = true, optional = true } +osmosis-std = { version = "0.19.2", optional = true } # Astroport astroport = { workspace = true, optional = true } +astroport_v3 = { workspace = true, optional = true } cw2 = { workspace = true, optional = true } [dev-dependencies] -cw-it = { workspace = true, features = ["osmosis", "astroport", "multi-test", "astroport-multi-test"] } -test-case = "3.0.0" +cw-it = { workspace = true, features = ["multi-test"] } +test-case = { workspace = true } cw-dex-test-contract = { workspace = true } -cw-dex-test-helpers = { workspace = true, features = ["osmosis", "astroport"] } -proptest = "1.0.0" +cw-dex-test-helpers = { workspace = true } +proptest = { workspace = true } cw20-base = { workspace = true } +cw20 = { workspace = true } diff --git a/cw-dex/src/implementations/astroport/pool.rs b/cw-dex/src/implementations/astroport/pool.rs index 06423549..1c0606a6 100644 --- a/cw-dex/src/implementations/astroport/pool.rs +++ b/cw-dex/src/implementations/astroport/pool.rs @@ -7,7 +7,7 @@ use apollo_utils::iterators::IntoElementwise; use astroport::liquidity_manager; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - to_binary, wasm_execute, Addr, CosmosMsg, Decimal, Deps, Env, Event, QuerierWrapper, + to_json_binary, wasm_execute, Addr, CosmosMsg, Decimal, Deps, Env, Event, QuerierWrapper, QueryRequest, Response, StdError, StdResult, Uint128, WasmMsg, WasmQuery, }; use cw20::Cw20ExecuteMsg; @@ -77,7 +77,7 @@ impl AstroportPool { pub fn query_pool_info(&self, querier: &QuerierWrapper) -> StdResult { querier.query::(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: self.pair_addr.to_string(), - msg: to_binary(&PairQueryMsg::Pool {})?, + msg: to_json_binary(&PairQueryMsg::Pool {})?, })) } } @@ -98,7 +98,7 @@ impl Pool for AstroportPool { .map(|asset| { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: asset.address, - msg: to_binary(&Cw20ExecuteMsg::IncreaseAllowance { + msg: to_json_binary(&Cw20ExecuteMsg::IncreaseAllowance { spender: self.liquidity_manager.to_string(), amount: asset.amount, expires: Some(Expiration::AtHeight(env.block.height + 1)), @@ -119,7 +119,7 @@ impl Pool for AstroportPool { // Create the provide liquidity message let provide_liquidity_msg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: self.liquidity_manager.to_string(), - msg: to_binary(&liquidity_manager::ExecuteMsg::ProvideLiquidity { + msg: to_json_binary(&liquidity_manager::ExecuteMsg::ProvideLiquidity { pair_addr: self.pair_addr.to_string(), min_lp_to_receive: Some(min_out), pair_msg: astroport::pair::ExecuteMsg::ProvideLiquidity { @@ -161,10 +161,10 @@ impl Pool for AstroportPool { let withdraw_liquidity = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: token_addr.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: self.liquidity_manager.to_string(), amount: asset.amount, - msg: to_binary(&liquidity_manager::Cw20HookMsg::WithdrawLiquidity { + msg: to_json_binary(&liquidity_manager::Cw20HookMsg::WithdrawLiquidity { pair_msg: astroport::pair::Cw20HookMsg::WithdrawLiquidity { // This field is currently not used... assets: vec![], @@ -220,7 +220,7 @@ impl Pool for AstroportPool { &Cw20ExecuteMsg::Send { contract: self.pair_addr.to_string(), amount: offer_asset.amount, - msg: to_binary(&PairCw20HookMsg::Swap { + msg: to_json_binary(&PairCw20HookMsg::Swap { belief_price, max_spread: Some(Decimal::zero()), to: Some(env.contract.address.to_string()), @@ -296,7 +296,7 @@ impl Pool for AstroportPool { .querier .query::(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: self.pair_addr.to_string(), - msg: to_binary(&PairQueryMsg::Simulation { + msg: to_json_binary(&PairQueryMsg::Simulation { offer_asset: offer_asset.into(), ask_asset_info: Some(ask_asset_info.into()), })?, diff --git a/cw-dex/src/implementations/astroport/staking.rs b/cw-dex/src/implementations/astroport/staking.rs index 2e9fa13f..28bf9e99 100644 --- a/cw-dex/src/implementations/astroport/staking.rs +++ b/cw-dex/src/implementations/astroport/staking.rs @@ -3,16 +3,16 @@ use apollo_utils::assets::separate_natives_and_cw20s; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - to_binary, Addr, CosmosMsg, Deps, Empty, Env, Event, QuerierWrapper, QueryRequest, Response, - Uint128, WasmMsg, WasmQuery, + to_json_binary, Addr, CosmosMsg, Deps, Empty, Env, Event, QuerierWrapper, QueryRequest, + Response, Uint128, WasmMsg, WasmQuery, }; use cw20::Cw20ExecuteMsg; -use apollo_cw_asset::{Asset, AssetInfo, AssetList}; +use apollo_cw_asset::AssetList; use astroport::asset::Asset as AstroAsset; -use astroport::generator::{ - Cw20HookMsg as GeneratorCw20HookMsg, ExecuteMsg as GeneratorExecuteMsg, PendingTokenResponse, - QueryMsg as GeneratorQueryMsg, +use astroport_v3::incentives::{ + Cw20Msg as IncentivesCw20Msg, ExecuteMsg as IncentivesExecuteMsg, + QueryMsg as IncentivesQueryMsg, }; use crate::traits::{Rewards, Stake, Staking, Unstake}; @@ -23,10 +23,8 @@ use crate::CwDexError; pub struct AstroportStaking { /// The address of the associated LP token contract pub lp_token_addr: Addr, - /// The address of the associated generator contract - pub generator_addr: Addr, - /// The address of the ASTRO token contract - pub astro_token: AssetInfo, + /// The address of the astroport incentives contract + pub incentives: Addr, } impl Staking for AstroportStaking {} @@ -35,10 +33,10 @@ impl Stake for AstroportStaking { fn stake(&self, _deps: Deps, _env: &Env, amount: Uint128) -> Result { let stake_msg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: self.lp_token_addr.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Send { - contract: self.generator_addr.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: self.incentives.to_string(), amount, - msg: to_binary(&GeneratorCw20HookMsg::Deposit {})?, + msg: to_json_binary(&IncentivesCw20Msg::Deposit { recipient: None })?, })?, funds: vec![], }); @@ -46,7 +44,7 @@ impl Stake for AstroportStaking { let event = Event::new("apollo/cw-dex/stake") .add_attribute("type", "astroport_staking") .add_attribute("asset", self.lp_token_addr.to_string()) - .add_attribute("generator_address", self.generator_addr.to_string()); + .add_attribute("incentives contract address", self.incentives.to_string()); Ok(Response::new().add_message(stake_msg).add_event(event)) } @@ -65,8 +63,8 @@ impl Rewards for AstroportStaking { } let claim_rewards_msg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: self.generator_addr.to_string(), - msg: to_binary(&GeneratorExecuteMsg::ClaimRewards { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesExecuteMsg::ClaimRewards { lp_tokens: vec![self.lp_token_addr.to_string()], })?, funds: vec![], @@ -97,10 +95,10 @@ impl Rewards for AstroportStaking { // Unwrap the native token let unwrap_msg: CosmosMsg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cw20.address.to_string(), - msg: to_binary(&cw20::Cw20ExecuteMsg::Send { + msg: to_json_binary(&cw20::Cw20ExecuteMsg::Send { contract: wrapper_contract.to_string(), amount: cw20.amount, - msg: to_binary(&astroport::native_coin_wrapper::Cw20HookMsg::Unwrap {})?, + msg: to_json_binary(&astroport::native_coin_wrapper::Cw20HookMsg::Unwrap {})?, })?, funds: vec![], }); @@ -115,25 +113,17 @@ impl Rewards for AstroportStaking { querier: &QuerierWrapper, user: &Addr, ) -> Result { - let PendingTokenResponse { - pending: pending_astro, - pending_on_proxy, - } = querier.query(&QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: self.generator_addr.to_string(), - msg: to_binary(&GeneratorQueryMsg::PendingToken { - lp_token: self.lp_token_addr.to_string(), - user: user.to_string(), - })?, - }))?; - - let pending_rewards: Vec = pending_on_proxy - .unwrap_or_default() + let pending_rewards: Vec = querier + .query::>(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesQueryMsg::PendingRewards { + lp_token: self.lp_token_addr.to_string(), + user: user.to_string(), + })?, + }))? .into_iter() - .chain(vec![ - Asset::new(self.astro_token.clone(), pending_astro).into() - ]) - .filter(|asset| !asset.amount.is_zero()) - .collect::>(); + .filter(|asset| !asset.amount.is_zero()) //TODO: Is this necessary? + .collect(); Ok(pending_rewards.into()) } @@ -142,8 +132,8 @@ impl Rewards for AstroportStaking { impl Unstake for AstroportStaking { fn unstake(&self, _deps: Deps, _env: &Env, amount: Uint128) -> Result { let unstake_msg = CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: self.generator_addr.to_string(), - msg: to_binary(&GeneratorExecuteMsg::Withdraw { + contract_addr: self.incentives.to_string(), + msg: to_json_binary(&IncentivesExecuteMsg::Withdraw { lp_token: self.lp_token_addr.to_string(), amount, })?, diff --git a/cw-dex/src/implementations/osmosis/pool.rs b/cw-dex/src/implementations/osmosis/pool.rs index 1a5dc43e..621a896a 100644 --- a/cw-dex/src/implementations/osmosis/pool.rs +++ b/cw-dex/src/implementations/osmosis/pool.rs @@ -305,24 +305,3 @@ impl Pool for OsmosisPool { AssetInfo::Native(format!("gamm/pool/{}", self.pool_id)) } } - -#[cfg(test)] -mod tests { - use apollo_cw_asset::AssetInfo; - - use crate::traits::Pool; - - use super::OsmosisPool; - - #[test] - fn test_lp_token() { - let pool = OsmosisPool::unchecked(1337u64); - - let lp_token = pool.lp_token(); - - match lp_token { - AssetInfo::Native(denom) => assert_eq!(denom, format!("gamm/pool/{}", 1337u64)), - AssetInfo::Cw20(_) => panic!("Unexpected cw20 token"), - } - } -} diff --git a/cw-dex/src/lib.rs b/cw-dex/src/lib.rs index c0855664..863ff5a7 100644 --- a/cw-dex/src/lib.rs +++ b/cw-dex/src/lib.rs @@ -10,15 +10,20 @@ //! interact with any of them. //! //! The currently supported decentralized exchanges are: -//! - [Osmosis](crate::implementations::osmosis) -//! - [Astroport](crate::implementations::astroport) +//! - [Osmosis] +//! - Via crate `cw-dex-osmosis` +//! - [Astroport] +//! - Via crate `cw-dex-astroport` pub mod error; -pub mod implementations; pub mod traits; +#[deprecated( + since = "0.5.2", + note = "Please use separate implementation crates such as `cw-dex-astroport`, and `cw-dex-osmosis` instead" +)] +pub mod implementations; + pub use error::*; +#[allow(deprecated)] pub use implementations::*; - -// #[cfg(test)] -// pub mod tests; diff --git a/cw-dex/tests/configs/terra.yaml b/cw-dex/tests/configs/terra.yaml deleted file mode 100644 index 34c33a93..00000000 --- a/cw-dex/tests/configs/terra.yaml +++ /dev/null @@ -1,97 +0,0 @@ -folder: "./tests/configs" -artifacts_folder: "./artifacts" -chain_config: - name: "terra" - chain_id: "localterra" - prefix: "terra" - denom: "uluna" - gas_price: 1000000 - gas_adjustment: 1.2 - # https://github.com/confio/cosmos-hd-key-derivation-spec#the-cosmos-hub-path - derivation_path: "m/44'/330'/0'/0/0" - - # leave this empty if using test_containers - rpc_endpoint: "" - grpc_endpoint: "" -container: - name: "terramoney/localterra-core" - tag: "2.0.1" - entrypoint: "/entrypoint.sh" - volumes: - [ - ["tests/configs/terra/config", "/root/.terra/config"], - ["tests/configs/terra/entrypoint.sh", "/entrypoint.sh"], - ] - ports: [26657, 1317, 9090, 9091] - -# Chain to download contracts from -contract_chain_download_rpc: "https://terra-rpc.polkachu.com" - -# contracts list to download -# Do not repeat names -contracts: - astroport_liquidity_helper: - url: "https://github.com/apollodao/astroport-liquidity-helper.git" - branch: "master" - artifact: astroport_liquidity_helper.wasm - preferred_source: "url" - - astro_token: - url: "https://github.com/astroport-fi/astroport-core.git" - branch: "c216ecd4f350113316be44d06a95569f451ac681" # TODO: Allow commit instead of branch - artifact: "astro_token.wasm" - preferred_source: "chain" # Where to prefer getting contract, can be either "chain" or "url". - chain_address: "terra1nsuqsk6kh58ulczatwev87ttq2z6r3pusulg9r24mfj2fvtzd4uq3exn26" - - astroport_factory: - artifact: "astroport_factory.wasm" - preferred_source: "chain" - chain_address: "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r" - - astroport_maker: - artifact: "astroport_maker.wasm" - preferred_source: "chain" - chain_address: "terra1ygcvxp9s054q8u2q4hvl52ke393zvgj0sllahlycm4mj8dm96zjsa45rzk" - - astroport_router: - artifact: "astroport_router.wasm" - preferred_source: "chain" - chain_address: "terra1j8hayvehh3yy02c2vtw5fdhz9f4drhtee8p5n5rguvg3nyd6m83qd2y90a" - - astroport_generator: - artifact: "astroport_generator.wasm" - preferred_source: "chain" - chain_address: "terra1ksvlfex49desf4c452j6dewdjs6c48nafemetuwjyj6yexd7x3wqvwa7j9" - - astroport_pair_stable: - artifact: "astroport_pair_stable.wasm" - preferred_source: "chain" - chain_code_id: 428 - - astroport_pair_xyk: - artifact: "astroport_pair_xyk.wasm" - preferred_source: "chain" - chain_code_id: 392 - - astroport_whitelist: - artifact: "astroport_whitelist.wasm" - preferred_source: "chain" - chain_code_id: 70 - - astroport_staking: - artifact: "astroport_staking.wasm" - preferred_source: "chain" - chain_address: "terra1nyu6sk9rvtvsltm7tjjrp6rlavnm3e4sq03kltde6kesam260f8szar8ze" - - astroport_vesting: - artifact: "astroport_vesting.wasm" - preferred_source: "chain" - chain_address: "terra1qyuarnzcc6uuft9n9mltraprreke4v8gvxd8u3nslngxhflhru9qw34nc3" - - cw_dex_router: - artifact: "cw_dex_router.wasm" - preferred_source: "chain" - - astroport_vault: - artifact: "astroport_vault.wasm" - preferred_source: "chain" diff --git a/deny.toml b/deny.toml index f7694436..10a6b5a3 100644 --- a/deny.toml +++ b/deny.toml @@ -33,4 +33,6 @@ copyleft = "deny" # We want really high confidence when inferring licenses from text confidence-threshold = 0.93 allow = ["Apache-2.0", "MIT", "BSD-3-Clause", "MPL-2.0"] -exceptions = [{ allow = ["Unicode-DFS-2016"], name = "unicode-ident" }] +exceptions = [ + { allow = ["Unicode-DFS-2016"], name = "unicode-ident" }, +] diff --git a/test-contracts/astroport-test-contract/Cargo.toml b/test-contracts/astroport-test-contract/Cargo.toml index 0a4028cb..027a0ce5 100644 --- a/test-contracts/astroport-test-contract/Cargo.toml +++ b/test-contracts/astroport-test-contract/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "astroport-test-contract" description = "Contract to test the cw-dex library" -version = "0.1.0" +version = "0.2.0" authors = ["Pacman "] edition = "2021" license = { workspace = true } @@ -36,5 +36,6 @@ cosmwasm-std = { workspace = true } cw-storage-plus = { workspace = true } thiserror = { workspace = true } apollo-cw-asset = { workspace = true } -cw-dex = { workspace = true, features = ["astroport"] } +cw-dex = { workspace = true } +cw-dex-astroport = { workspace = true } cw-dex-test-contract = { workspace = true } diff --git a/test-contracts/astroport-test-contract/src/contract.rs b/test-contracts/astroport-test-contract/src/contract.rs index ae85bc8f..b2c2a86e 100644 --- a/test-contracts/astroport-test-contract/src/contract.rs +++ b/test-contracts/astroport-test-contract/src/contract.rs @@ -4,10 +4,11 @@ use apollo_cw_asset::{Asset, AssetInfo, AssetList}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, Uint128, + to_json_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, + Uint128, }; -use cw_dex::astroport::{AstroportPool, AstroportStaking}; -use cw_dex::traits::{Pool, Stake, Unstake}; +use cw_dex::traits::{Pool, Rewards, Stake, Unstake}; +use cw_dex_astroport::{AstroportPool, AstroportStaking}; use cw_dex_test_contract::msg::{ AstroportContractInstantiateMsg as InstantiateMsg, AstroportExecuteMsg as ExecuteMsg, QueryMsg, }; @@ -29,9 +30,7 @@ pub fn instantiate( &AstroportStaking { lp_token_addr: Addr::unchecked(msg.lp_token_addr), - generator_addr: Addr::unchecked(msg.generator_addr), - - astro_token: msg.astro_token, + incentives: Addr::unchecked(msg.incentives_addr), }, )?; @@ -54,6 +53,7 @@ pub fn execute( } ExecuteMsg::Stake { amount } => execute_stake(deps, env, info, amount), ExecuteMsg::Unstake { amount } => execute_unstake(deps, env, info, amount), + ExecuteMsg::ClaimRewards {} => execute_claim_rewards(deps, env, info), ExecuteMsg::Swap { offer, ask, @@ -111,6 +111,15 @@ pub fn execute_unstake( Ok(staking.unstake(deps.as_ref(), &env, amount)?) } +pub fn execute_claim_rewards( + deps: DepsMut, + env: Env, + _info: MessageInfo, +) -> Result { + let staking = STAKING.load(deps.storage)?; + Ok(staking.claim_rewards(deps.as_ref(), &env)?) +} + pub fn execute_swap( deps: DepsMut, env: Env, @@ -127,23 +136,27 @@ pub fn execute_swap( pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let pool = POOL.load(deps.storage)?; match msg { - QueryMsg::PoolLiquidity {} => to_binary(&pool.get_pool_liquidity(deps)?), + QueryMsg::PoolLiquidity {} => to_json_binary(&pool.get_pool_liquidity(deps)?), QueryMsg::SimulateProvideLiquidity { assets } => { - to_binary(&pool.simulate_provide_liquidity(deps, &env, assets)?.amount) + to_json_binary(&pool.simulate_provide_liquidity(deps, &env, assets)?.amount) } - QueryMsg::SimulateWithdrawLiquidty { amount } => to_binary( + QueryMsg::SimulateWithdrawLiquidty { amount } => to_json_binary( &pool.simulate_withdraw_liquidity(deps, &Asset::new(pool.lp_token(), amount))?, ), QueryMsg::SimulateSwap { offer, ask } => query_simulate_swap(deps, offer, ask), - QueryMsg::GetPoolForLpToken { lp_token } => to_binary( - &cw_dex::Pool::get_pool_for_lp_token(deps, &lp_token, Some(pool.liquidity_manager))?, + QueryMsg::GetPoolForLpToken { lp_token } => to_json_binary( + &AstroportPool::get_pool_for_lp_token(deps, &lp_token, pool.liquidity_manager)?, ), + QueryMsg::PendingRewards {} => { + let staking = STAKING.load(deps.storage)?; + to_json_binary(&staking.query_pending_rewards(&deps.querier, &env.contract.address)?) + } } } pub fn query_simulate_swap(deps: Deps, offer: Asset, ask: AssetInfo) -> StdResult { let pool = POOL.load(deps.storage)?; - to_binary(&pool.simulate_swap(deps, offer, ask)?) + to_json_binary(&pool.simulate_swap(deps, offer, ask)?) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/test-contracts/astroport-test-contract/src/state.rs b/test-contracts/astroport-test-contract/src/state.rs index 7a4ff83b..49a2d85e 100644 --- a/test-contracts/astroport-test-contract/src/state.rs +++ b/test-contracts/astroport-test-contract/src/state.rs @@ -1,4 +1,4 @@ -use cw_dex::astroport::{AstroportPool, AstroportStaking}; +use cw_dex_astroport::{AstroportPool, AstroportStaking}; use cw_storage_plus::Item; pub const POOL: Item = Item::new("pool"); diff --git a/test-contracts/osmosis-test-contract/Cargo.toml b/test-contracts/osmosis-test-contract/Cargo.toml index 95a9ddb9..f078b64c 100644 --- a/test-contracts/osmosis-test-contract/Cargo.toml +++ b/test-contracts/osmosis-test-contract/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "osmosis-test-contract" description = "Contract to test the cw-dex library" -version = "0.1.0" +version = "0.2.0" authors = ["Pacman "] edition = "2021" license = { workspace = true } @@ -36,5 +36,6 @@ cosmwasm-std = { workspace = true } cw-storage-plus = { workspace = true } thiserror = { workspace = true } apollo-cw-asset = { workspace = true } -cw-dex = { workspace = true, features = ["osmosis"] } +cw-dex = { workspace = true } +cw-dex-osmosis = { workspace = true } cw-dex-test-contract = { workspace = true } diff --git a/test-contracts/osmosis-test-contract/src/contract.rs b/test-contracts/osmosis-test-contract/src/contract.rs index aeaf7511..f04594f7 100644 --- a/test-contracts/osmosis-test-contract/src/contract.rs +++ b/test-contracts/osmosis-test-contract/src/contract.rs @@ -2,23 +2,16 @@ use apollo_cw_asset::{Asset, AssetInfo, AssetList}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, StdResult, Uint128, }; -use cw_dex::osmosis::{OsmosisPool, OsmosisStaking, OsmosisSuperfluidStaking}; use cw_dex::traits::{ForceUnlock, Pool, Stake, Unlock}; -// use cw2::set_contract_version; +use cw_dex_osmosis::{OsmosisPool, OsmosisStaking, OsmosisSuperfluidStaking}; use crate::error::ContractError; use crate::state::{POOL, STAKING, SUPERFLUID}; use cw_dex_test_contract::msg::{ExecuteMsg, OsmosisTestContractInstantiateMsg, QueryMsg}; -/* -// version info for migration info -const CONTRACT_NAME: &str = "crates.io:cw-dex-test-contract"; -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -*/ - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -204,23 +197,24 @@ pub fn execute_swap( pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let pool = POOL.load(deps.storage)?; match msg { - QueryMsg::PoolLiquidity {} => to_binary(&pool.get_pool_liquidity(deps)?), + QueryMsg::PoolLiquidity {} => to_json_binary(&pool.get_pool_liquidity(deps)?), QueryMsg::SimulateProvideLiquidity { assets } => { - to_binary(&pool.simulate_provide_liquidity(deps, &env, assets)?.amount) + to_json_binary(&pool.simulate_provide_liquidity(deps, &env, assets)?.amount) } - QueryMsg::SimulateWithdrawLiquidty { amount } => to_binary( + QueryMsg::SimulateWithdrawLiquidty { amount } => to_json_binary( &pool.simulate_withdraw_liquidity(deps, &Asset::new(pool.lp_token(), amount))?, ), QueryMsg::SimulateSwap { offer, ask } => query_simulate_swap(deps, offer, ask), QueryMsg::GetPoolForLpToken { lp_token } => { - to_binary(&cw_dex::Pool::get_pool_for_lp_token(deps, &lp_token, None)?) + to_json_binary(&OsmosisPool::get_pool_for_lp_token(deps, &lp_token)?) } + QueryMsg::PendingRewards {} => unimplemented!(), } } pub fn query_simulate_swap(deps: Deps, offer: Asset, ask: AssetInfo) -> StdResult { let pool = POOL.load(deps.storage)?; - to_binary(&pool.simulate_swap(deps, offer, ask)?) + to_json_binary(&pool.simulate_swap(deps, offer, ask)?) } #[cfg_attr(not(feature = "library"), entry_point)] diff --git a/test-contracts/osmosis-test-contract/src/state.rs b/test-contracts/osmosis-test-contract/src/state.rs index fbbbff17..66c16f90 100644 --- a/test-contracts/osmosis-test-contract/src/state.rs +++ b/test-contracts/osmosis-test-contract/src/state.rs @@ -1,4 +1,4 @@ -use cw_dex::osmosis::{OsmosisPool, OsmosisStaking, OsmosisSuperfluidStaking}; +use cw_dex_osmosis::{OsmosisPool, OsmosisStaking, OsmosisSuperfluidStaking}; use cw_storage_plus::Item; pub const POOL: Item = Item::new("pool"); diff --git a/test-contracts/package/Cargo.toml b/test-contracts/package/Cargo.toml index fc9cc0f7..c944f290 100644 --- a/test-contracts/package/Cargo.toml +++ b/test-contracts/package/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cw-dex-test-contract" description = "Contract to test the cw-dex library" -version = "0.1.0" +version = "0.2.0" authors = ["Pacman "] edition = "2021" license = { workspace = true } @@ -21,4 +21,3 @@ crate-type = ["cdylib", "rlib"] cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } apollo-cw-asset = { workspace = true } -cw-dex = { workspace = true } diff --git a/test-contracts/package/src/msg.rs b/test-contracts/package/src/msg.rs index 06c30e7b..dffec8d3 100644 --- a/test-contracts/package/src/msg.rs +++ b/test-contracts/package/src/msg.rs @@ -1,6 +1,6 @@ use apollo_cw_asset::{Asset, AssetInfo, AssetList}; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{to_binary, Addr, Coin, CosmosMsg, Uint128, WasmMsg}; +use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, Uint128, WasmMsg}; #[cw_serde] pub struct OsmosisTestContractInstantiateMsg { @@ -14,7 +14,7 @@ pub struct OsmosisTestContractInstantiateMsg { pub struct AstroportContractInstantiateMsg { pub pair_addr: String, pub lp_token_addr: String, - pub generator_addr: String, + pub incentives_addr: String, pub astro_token: AssetInfo, pub liquidity_manager_addr: String, } @@ -59,12 +59,18 @@ impl ExecuteMsg { pub fn into_cosmos_msg(&self, contract_addr: String, funds: Vec) -> CosmosMsg { CosmosMsg::Wasm(WasmMsg::Execute { contract_addr, - msg: to_binary(self).unwrap(), + msg: to_json_binary(self).unwrap(), funds, }) } } +#[cw_serde] +/// Represents an unknown type as the response of a query. +/// This is due to the API being used by different contracts which will return +/// different types. +pub struct Unknown {} + #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { @@ -76,8 +82,10 @@ pub enum QueryMsg { SimulateWithdrawLiquidty { amount: Uint128 }, #[returns(Uint128)] SimulateSwap { offer: Asset, ask: AssetInfo }, - #[returns(cw_dex::Pool)] + #[returns(Unknown)] GetPoolForLpToken { lp_token: AssetInfo }, + #[returns(AssetList)] + PendingRewards {}, } #[cw_serde] @@ -96,6 +104,7 @@ pub enum AstroportExecuteMsg { Unstake { amount: Uint128, }, + ClaimRewards {}, Swap { offer: Asset, ask: AssetInfo, @@ -107,7 +116,7 @@ impl AstroportExecuteMsg { pub fn into_cosmos_msg(&self, contract_addr: String, funds: Vec) -> CosmosMsg { CosmosMsg::Wasm(WasmMsg::Execute { contract_addr, - msg: to_binary(self).unwrap(), + msg: to_json_binary(self).unwrap(), funds, }) } diff --git a/test-helpers/Cargo.toml b/test-helpers/Cargo.toml index 163535b1..e6de23e4 100644 --- a/test-helpers/Cargo.toml +++ b/test-helpers/Cargo.toml @@ -16,7 +16,7 @@ exclude = [ [features] default = [] osmosis = ["cw-it/osmosis"] -astroport = ["cw-it/astroport", "cw-it/astroport-multi-test", "astroport-test-contract"] +astroport = ["cw-it/astroport", "cw-it/astroport-multi-test", "astroport-test-contract", "apollo-cw-asset/astroport"] osmosis-test-tube = ["cw-it/osmosis-test-tube"] [lib] @@ -31,7 +31,7 @@ optimize = """docker run --rm -v "$(pwd)":/code \ [dependencies] cosmwasm-std = { workspace = true } -apollo-cw-asset = { workspace = true, features = ["astroport"] } +apollo-cw-asset = { workspace = true } apollo-utils = { workspace = true } cw-dex-test-contract = { workspace = true } astroport-test-contract = { workspace = true, optional = true } diff --git a/test-helpers/src/astroport.rs b/test-helpers/src/astroport.rs index 860efbbd..7653c014 100644 --- a/test-helpers/src/astroport.rs +++ b/test-helpers/src/astroport.rs @@ -3,11 +3,13 @@ use apollo_utils::assets::separate_natives_and_cw20s; use astroport::asset::{Asset as AstroAsset, AssetInfo as AstroAssetInfo}; use astroport::factory::PairType; use astroport::pair::{ExecuteMsg as PairExecuteMsg, StablePoolParams}; -use cosmwasm_std::{to_binary, Addr, Coin, Decimal, Uint128}; +use cosmwasm_std::{to_json_binary, Addr, Coin, Decimal, Uint128}; use cw20::{Cw20ExecuteMsg, MinterResponse}; use cw20_base::msg::InstantiateMsg as Cw20InstantiateMsg; use cw_dex_test_contract::msg::AstroportContractInstantiateMsg; -use cw_it::astroport::utils::{create_astroport_pair, get_local_contracts, setup_astroport}; +use cw_it::astroport::utils::{ + create_astroport_pair, get_local_contracts, setup_astroport, AstroportContracts, +}; use cw_it::cw_multi_test::ContractWrapper; use cw_it::helpers::upload_wasm_file; use cw_it::test_tube::{Account, Module, Runner, RunnerResult, SigningAccount, Wasm}; @@ -28,7 +30,14 @@ pub fn setup_pool_and_test_contract<'a>( initial_liquidity: Vec<(&str, u64)>, native_denom_count: usize, wasm_file_path: &str, -) -> RunnerResult<(Vec, String, String, String, AssetList)> { +) -> RunnerResult<( + Vec, + String, + String, + String, + AssetList, + AstroportContracts, +)> { let wasm = Wasm::new(runner); // Initialize 10 accounts with max balance of each token @@ -190,14 +199,14 @@ pub fn setup_pool_and_test_contract<'a>( // Create pool let init_params = match &pool_type { PairType::Stable {} => Some( - to_binary(&StablePoolParams { + to_json_binary(&StablePoolParams { amp: 10u64, owner: None, }) .unwrap(), ), PairType::Custom(t) => match t.as_str() { - "concentrated" => Some(to_binary(&common_pcl_params()).unwrap()), + "concentrated" => Some(to_json_binary(&common_pcl_params()).unwrap()), _ => None, }, _ => None, @@ -261,14 +270,23 @@ pub fn setup_pool_and_test_contract<'a>( runner, code_id, pair_addr.clone(), - astroport_contracts.generator.address, - AssetInfo::cw20(Addr::unchecked(astroport_contracts.astro_token.address)), + astroport_contracts.incentives.address.clone(), + AssetInfo::cw20(Addr::unchecked( + astroport_contracts.astro_token.address.clone(), + )), lp_token_addr.clone(), - astroport_contracts.liquidity_manager.address, + astroport_contracts.liquidity_manager.address.clone(), &accs[0], )?; - Ok((accs, lp_token_addr, pair_addr, contract_addr, asset_list)) + Ok(( + accs, + lp_token_addr, + pair_addr, + contract_addr, + asset_list, + astroport_contracts, + )) } #[allow(clippy::too_many_arguments)] @@ -276,7 +294,7 @@ pub fn instantiate_test_astroport_contract<'a, R: Runner<'a>>( runner: &'a R, code_id: u64, pair_addr: String, - generator_addr: String, + incentives_addr: String, astro_token: AssetInfo, lp_token_addr: String, liquidity_manager_addr: String, @@ -285,14 +303,14 @@ pub fn instantiate_test_astroport_contract<'a, R: Runner<'a>>( let init_msg = AstroportContractInstantiateMsg { pair_addr, lp_token_addr, - generator_addr, + incentives_addr, astro_token, liquidity_manager_addr, }; let wasm = Wasm::new(runner); Ok(wasm - .instantiate(code_id, &init_msg, None, None, &[], signer)? + .instantiate(code_id, &init_msg, None, Some("test contract"), &[], signer)? .data .address) } diff --git a/test-helpers/src/osmosis.rs b/test-helpers/src/osmosis.rs index 95438f99..346fc233 100644 --- a/test-helpers/src/osmosis.rs +++ b/test-helpers/src/osmosis.rs @@ -86,7 +86,7 @@ pub fn instantiate_test_contract<'a, R: Runner<'a>>( let wasm = Wasm::new(runner); Ok(wasm - .instantiate(code_id, &init_msg, None, None, &[], signer)? + .instantiate(code_id, &init_msg, None, Some("test contract"), &[], signer)? .data .address) }