From ab4cd9f1215025a2e03222dac5f634fbcd524a4d Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 24 Sep 2024 14:36:46 +0100 Subject: [PATCH 1/7] feat: added test-tube tests --- Cargo.lock | 3359 +++++++++++++++-- Cargo.toml | 79 +- build_release.sh | 2 +- contracts/cw20-adapter/Cargo.toml | 50 +- contracts/cw20-adapter/src/contract.rs | 6 +- contracts/cw20-adapter/src/execute_receive.rs | 4 + contracts/cw20-adapter/src/execute_redeem.rs | 13 +- contracts/cw20-adapter/src/lib.rs | 3 + .../{tests => src/testing}/common/mod.rs | 0 .../cw20-adapter/src/testing/instantiation.rs | 41 + contracts/cw20-adapter/src/testing/mod.rs | 6 + contracts/cw20-adapter/src/testing/query.rs | 29 + contracts/cw20-adapter/src/testing/receive.rs | 72 + contracts/cw20-adapter/src/testing/redeem.rs | 89 + .../cw20-adapter/src/testing/register.rs | 134 + .../src/testing/test_artifacts/cw20_base.wasm | Bin 0 -> 269740 bytes contracts/cw20-adapter/src/testing/utils.rs | 142 + .../tests/execute_metadata_tests.rs | 63 - .../tests/execute_receive_tests.rs | 152 - .../tests/execute_redeem_tests.rs | 170 - .../tests/execute_register_tests.rs | 201 - .../cw20-adapter/tests/integration_test.rs | 48 - packages/testenv/Cargo.toml | 26 + packages/testenv/src/lib.rs | 1 + packages/testenv/src/utils.rs | 76 + 25 files changed, 3690 insertions(+), 1076 deletions(-) rename contracts/cw20-adapter/{tests => src/testing}/common/mod.rs (100%) create mode 100644 contracts/cw20-adapter/src/testing/instantiation.rs create mode 100644 contracts/cw20-adapter/src/testing/mod.rs create mode 100644 contracts/cw20-adapter/src/testing/query.rs create mode 100644 contracts/cw20-adapter/src/testing/receive.rs create mode 100644 contracts/cw20-adapter/src/testing/redeem.rs create mode 100644 contracts/cw20-adapter/src/testing/register.rs create mode 100644 contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm create mode 100644 contracts/cw20-adapter/src/testing/utils.rs delete mode 100644 contracts/cw20-adapter/tests/execute_metadata_tests.rs delete mode 100644 contracts/cw20-adapter/tests/execute_receive_tests.rs delete mode 100644 contracts/cw20-adapter/tests/execute_redeem_tests.rs delete mode 100644 contracts/cw20-adapter/tests/execute_register_tests.rs delete mode 100644 contracts/cw20-adapter/tests/integration_test.rs create mode 100644 packages/testenv/Cargo.toml create mode 100644 packages/testenv/src/lib.rs create mode 100644 packages/testenv/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 713abc7..7ab439f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,22 +2,233 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "getrandom", + "cfg-if", "once_cell", "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.103", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", + "rayon", +] + +[[package]] +name = "arrayvec" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" +dependencies = [ + "nodrop", + "odds", +] + +[[package]] +name = "async-trait" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[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", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] name = "base16ct" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" @@ -25,6 +236,18 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.5.3" @@ -32,13 +255,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" [[package]] -name = "bigint" -version = "4.4.3" +name = "bech32" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bindgen" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" dependencies = [ - "byteorder", - "crunchy 0.1.6", + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bip32" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" +dependencies = [ + "bs58", + "hmac", + "k256", + "rand_core 0.6.4", + "ripemd", + "sha2 0.10.8", + "subtle", + "zeroize", ] [[package]] @@ -47,6 +305,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "block-buffer" version = "0.9.0" @@ -65,112 +329,293 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bnum" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "sha2 0.10.8", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "cc" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "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 1.9.3", + "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 = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "const-oid" -version = "0.9.1" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cosmos-sdk-proto" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" +dependencies = [ + "prost 0.12.6", + "prost-types 0.12.6", + "tendermint-proto 0.34.1", +] + +[[package]] +name = "cosmrs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea" +dependencies = [ + "bip32", + "cosmos-sdk-proto", + "ecdsa", + "eyre", + "k256", + "rand_core 0.6.4", + "serde 1.0.210", + "serde_json 1.0.87", + "signature", + "subtle-encoding", + "tendermint", + "tendermint-rpc", + "thiserror", +] + +[[package]] +name = "cosmwasm-core" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" +checksum = "5f6ceb8624260d0d3a67c4e1a1d43fc7e9406720afbcb124521501dd138f90aa" [[package]] name = "cosmwasm-crypto" -version = "1.1.6" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fc6d95cc171e56882d3e90689be1b38fecd31a4e6981129fc4973409de18b9" +checksum = "4125381e5fd7fefe9f614640049648088015eca2b60d861465329a5d87dfa538" dependencies = [ - "digest 0.10.6", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cosmwasm-core", + "digest 0.10.7", + "ecdsa", "ed25519-zebra", "k256", + "num-traits", + "p256", "rand_core 0.6.4", + "rayon", + "sha2 0.10.8", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.1.6" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a552716cf87ad173cd6b593fd72bf24fab490e0e5420aa75a227d6817d06b5df" +checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" dependencies = [ - "syn", + "proc-macro2", + "quote", + "syn 2.0.77", ] [[package]] name = "cosmwasm-schema" -version = "1.1.6" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c025d629589ca5d43fb8ff06decc387a4d01ead14f6b505300777fc6f01e1d" +checksum = "f86b4d949b6041519c58993a73f4bbfba8083ba14f7001eae704865a09065845" dependencies = [ "cosmwasm-schema-derive", "schemars", - "serde", - "serde_json", + "serde 1.0.210", + "serde_json 1.0.87", "thiserror", ] [[package]] name = "cosmwasm-schema-derive" -version = "1.1.6" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f09a65d22861a24a1b30eab6aa6759333723629bc2cb568cd22569745e1dcb2" +checksum = "c8ef1b5835a65fcca3ab8b9a02b4f4dacc78e233a5c2f20b270efb9db0666d12" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.77", ] [[package]] name = "cosmwasm-std" -version = "1.1.6" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1240e76655f4b858b3fb94befbf48e253e92c6640d9d674a1491d15f10bc4d72" +checksum = "70eb7ab0c1e99dd6207496963ba2a457c4128ac9ad9c72a83f8d9808542b849b" dependencies = [ - "base64", + "base64 0.22.1", + "bech32", + "bnum", + "cosmwasm-core", "cosmwasm-crypto", "cosmwasm-derive", - "derivative", - "forward_ref", + "derive_more", "hex", + "rand_core 0.6.4", "schemars", - "serde", + "serde 1.0.210", "serde-json-wasm", + "sha2 0.10.8", + "static_assertions 1.1.0", "thiserror", - "uint 0.9.4", ] [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] -name = "crunchy" -version = "0.1.6" +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -180,9 +625,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.4.9" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -202,115 +647,216 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] [[package]] -name = "cw-item-set" -version = "0.6.0" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05dad9dc2e6e9ab784bb5598d8528f4afe014b7b0ec05e1f466fe2e11aca368c" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.16.0", + "proc-macro2", + "quote", + "syn 2.0.77", ] [[package]] -name = "cw-storage-plus" -version = "0.15.1" +name = "curve25519-dalek-ng" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ - "cosmwasm-std", - "schemars", - "serde", + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "cw-item-set" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceb19026bd0d24ca3e81f2447bf2682c769e2b3c464eb1a7dcb643b626e7e83a" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", +] + +[[package]] +name = "cw-multi-test" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0ae276e7a06ad1b7e7da78a3d68aba80634cde30ee7fe8259a94e653603fef8" +dependencies = [ + "anyhow", + "bech32", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "derivative", + "itertools 0.13.0", + "prost 0.13.3", + "schemars", + "serde 1.0.210", + "sha2 0.10.8", + "thiserror", ] [[package]] name = "cw-storage-plus" -version = "0.16.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" dependencies = [ "cosmwasm-std", "schemars", - "serde", + "serde 1.0.210", ] [[package]] name = "cw-utils" -version = "0.16.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2", "schemars", - "semver", - "serde", + "serde 1.0.210", "thiserror", ] [[package]] name = "cw2" -version = "0.16.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 0.16.0", + "cw-storage-plus", "schemars", - "serde", + "semver", + "serde 1.0.210", + "thiserror", ] [[package]] name = "cw20" -version = "0.16.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45a8794a5dd33b66af34caee52a7beceb690856adcc1682b6e3db88b2cdee62" +checksum = "a42212b6bf29bbdda693743697c621894723f35d3db0d5df930be22903d0e27c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-utils", "schemars", - "serde", + "serde 1.0.210", ] [[package]] name = "cw20-adapter" -version = "1.0.0" +version = "2.0.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-item-set", - "cw-storage-plus 0.16.0", + "cw-storage-plus", "cw2", "cw20", + "cw20-base", "injective-cosmwasm", - "serde", + "injective-std", + "injective-test-tube", + "injective-testing", + "serde 1.0.210", + "testenv", + "thiserror", +] + +[[package]] +name = "cw20-base" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6de8c32e100f1fca306972d86b617234a5e6b00594ea2b48716fd6804d4d95d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "cw2", + "cw20", + "schemars", + "semver", + "serde 1.0.210", "thiserror", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + [[package]] name = "der" -version = "0.6.0" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -319,7 +865,28 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", + "unicode-xid", ] [[package]] @@ -333,11 +900,12 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.3", + "const-oid", "crypto-common", "subtle", ] @@ -350,41 +918,71 @@ checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "ecdsa" -version = "0.14.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", ] [[package]] name = "ed25519-zebra" -version = "3.1.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek", - "hashbrown", + "ed25519", + "hashbrown 0.14.5", "hex", "rand_core 0.6.4", - "serde", - "sha2 0.9.9", + "sha2 0.10.8", "zeroize", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "elliptic-curve" -version = "0.12.3" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "der", - "digest 0.10.6", + "digest 0.10.7", "ff", "generic-array", "group", @@ -395,14 +993,74 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enumset" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +dependencies = [ + "enumset_derive", + "serde 1.0.210", +] + +[[package]] +name = "enumset_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "ethbloom" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3932e82d64d347a045208924002930dc105a138995ccdc1479d0f05f0359f17c" dependencies = [ - "crunchy 0.2.2", - "fixed-hash", + "crunchy", + "fixed-hash 0.3.2", "impl-rlp", "impl-serde", "tiny-keccak", @@ -414,11 +1072,11 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b054df51e53f253837ea422681215b42823c02824bde982699d0dceecf6165a1" dependencies = [ - "crunchy 0.2.2", + "crunchy", "ethbloom", "ethereum-types-serialize", - "fixed-hash", - "serde", + "fixed-hash 0.3.2", + "serde 1.0.210", "uint 0.5.0", ] @@ -428,19 +1086,35 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" dependencies = [ - "serde", + "serde 1.0.210", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", ] [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fixed-hash" version = "0.3.2" @@ -449,16 +1123,44 @@ checksum = "d1a683d1234507e4f3bf2736eeddf0de1dc65996dc0164d57eba0a74bcf29489" dependencies = [ "byteorder", "heapsize", - "rand", + "rand 0.5.6", "rustc-hex", "static_assertions 0.2.5", ] [[package]] -name = "forward_ref" -version = "1.0.0" +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions 1.1.0", +] + +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "eyre", + "paste", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] [[package]] name = "fuchsia-cprng" @@ -466,6 +1168,73 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generic-array" version = "0.14.6" @@ -474,37 +1243,87 @@ checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.5.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", + "allocator-api2", ] [[package]] @@ -516,11 +1335,29 @@ dependencies = [ "winapi", ] +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde 1.0.210", +] [[package]] name = "hmac" @@ -528,53 +1365,289 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] -name = "impl-rlp" -version = "0.2.1" +name = "home" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "rlp", + "windows-sys 0.52.0", ] [[package]] -name = "impl-serde" -version = "0.2.3" +name = "http" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "serde", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "injective-cosmwasm" -version = "0.1.74" -source = "git+https://github.com/InjectiveLabs/cw-injective.git?branch=dev#f0c00001f04ee004f9c97ecbe012127c7111bc44" +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "cosmwasm-std", - "cw-storage-plus 0.15.1", - "ethereum-types", - "injective-math", - "schemars", - "serde", - "serde_repr", - "subtle-encoding", + "bytes", + "http", + "pin-project-lite", ] [[package]] -name = "injective-math" -version = "0.1.9" -source = "git+https://github.com/InjectiveLabs/cw-injective.git?branch=dev#f0c00001f04ee004f9c97ecbe012127c7111bc44" -dependencies = [ - "bigint", - "cosmwasm-std", - "ethereum-types", - "schemars", - "serde", - "subtle-encoding", +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +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.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-rlp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "injective-cosmwasm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e93e9438844b10add3eb40ed1e8c92689824ac080d207f856412a73551c221" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", + "ethereum-types", + "hex", + "injective-math", + "schemars", + "serde 1.0.210", + "serde_repr", + "subtle-encoding", + "tiny-keccak", +] + +[[package]] +name = "injective-math" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194fb5cb49537b0b9137d02a563b7019003220fb4affff05ad6cdc6fee3509c9" +dependencies = [ + "cosmwasm-std", + "ethereum-types", + "primitive-types", + "schemars", + "serde 1.0.210", + "subtle-encoding", +] + +[[package]] +name = "injective-std" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0e5193cb9520754f60b9e9af08a662ddf298d2e1a579200b9a447064b64db8b" +dependencies = [ + "chrono", + "cosmwasm-std", + "injective-std-derive", + "prost 0.12.6", + "prost-types 0.12.6", + "schemars", + "serde 1.0.210", + "serde-cw-value", +] + +[[package]] +name = "injective-std-derive" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2721d8c2fed1fd1dff4cd6d119711a74acf27a6eeea6bf09cd44d192119e52ea" +dependencies = [ + "cosmwasm-std", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "injective-test-tube" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a45747c74fca8aedafd94df74c6b9edf091c586ead96957e3c17e96abd6228b" +dependencies = [ + "base64 0.21.7", + "bindgen", + "cosmrs", + "cosmwasm-std", + "hex", + "injective-cosmwasm", + "injective-std", + "prost 0.12.6", + "serde 1.0.210", + "serde_json 1.0.87", + "test-tube-inj", + "thiserror", +] + +[[package]] +name = "injective-testing" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0012164e64110a7a630ab7352679b456c1b3fde71d641c2951c285c9ebe20daa" +dependencies = [ + "anyhow", + "base64 0.13.1", + "cosmwasm-std", + "cw-multi-test", + "injective-cosmwasm", + "injective-math", + "injective-std", + "injective-test-tube", + "prost 0.12.6", + "rand 0.4.6", + "secp256k1", + "serde 1.0.210", + "tiny-keccak", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[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.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", ] [[package]] @@ -583,428 +1656,1966 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "k256" -version = "0.11.6" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.8", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" -version = "0.2.137" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +dependencies = [ + "num-bigint 0.1.44", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" +dependencies = [ + "num-integer", + "num-traits", + "rand 0.4.6", + "rustc-serialize", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" +dependencies = [ + "num-traits", + "rustc-serialize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +dependencies = [ + "num-bigint 0.1.44", + "num-integer", + "num-traits", + "rustc-serialize", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "odds" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.8", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[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.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "295283b02df346d1ef66052a757869b2876ac29a6bb0ac3f5f7cd44aebe40e8f" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", + "uint 0.9.5", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive 0.13.3", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "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 1.0.210", + "serde_json 1.0.87", + "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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rlp" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73" +dependencies = [ + "rustc-hex", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc-serialize" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "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.7", +] + +[[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 = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "enumset", + "schemars_derive", + "serde 1.0.210", + "serde_json 1.0.87", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.77", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10915a2fa4f8016ed747eb847f096b0d44b22c6b624a36d3cc76964f6af4821a" +dependencies = [ + "arrayvec", + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "serde 0.6.15", + "serde_json 0.6.1", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" +dependencies = [ + "num", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-cw-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75d32da6b8ed758b7d850b6c3c08f1d7df51a4df3cb201296e63e34a78e99d4" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "serde-json-wasm" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_json" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" +dependencies = [ + "num", + "serde 0.6.15", +] + +[[package]] +name = "serde_json" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +dependencies = [ + "itoa", + "ryu", + "serde 1.0.210", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde 1.0.210", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" + +[[package]] +name = "static_assertions" +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 = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +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.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +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 = "tendermint" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256", + "num-traits", + "once_cell", + "prost 0.12.6", + "prost-types 0.12.6", + "ripemd", + "serde 1.0.210", + "serde_bytes", + "serde_json 1.0.87", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto 0.34.1", + "time", + "zeroize", +] + +[[package]] +name = "tendermint-config" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" +dependencies = [ + "flex-error", + "serde 1.0.210", + "serde_json 1.0.87", + "tendermint", + "toml", + "url", +] + +[[package]] +name = "tendermint-proto" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cec054567d16d85e8c3f6a3139963d1a66d9d3051ed545d31562550e9bcc3d" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.11.9", + "prost-types 0.11.9", + "serde 1.0.210", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.12.6", + "prost-types 0.12.6", + "serde 1.0.210", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-rpc" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" +dependencies = [ + "async-trait", + "bytes", + "flex-error", + "futures", + "getrandom", + "peg", + "pin-project", + "rand 0.8.5", + "reqwest", + "semver", + "serde 1.0.210", + "serde_bytes", + "serde_json 1.0.87", + "subtle", + "subtle-encoding", + "tendermint", + "tendermint-config", + "tendermint-proto 0.34.1", + "thiserror", + "time", + "tokio", + "tracing", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-tube-inj" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3a4e34619e6417613fab682de9a196848f4a56653ac71b95b5860b6d87c7cd" +dependencies = [ + "base64 0.21.7", + "cosmrs", + "cosmwasm-std", + "prost 0.12.6", + "serde 1.0.210", + "serde_json 1.0.87", + "tendermint-proto 0.32.2", + "thiserror", +] + +[[package]] +name = "testenv" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", + "enumset", + "injective-cosmwasm", + "injective-math", + "injective-std", + "injective-test-tube", + "injective-testing", + "prost 0.12.6", + "schemars", + "serde 1.0.210", + "serde-cw-value", + "serde-json-wasm", + "thiserror", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde 1.0.210", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde 1.0.210", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "uint" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" +dependencies = [ + "byteorder", + "crunchy", + "heapsize", + "rustc-hex", +] [[package]] -name = "once_cell" -version = "1.16.0" +name = "uint" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions 1.1.0", +] [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "unicode-bidi" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] -name = "pkcs8" -version = "0.9.0" +name = "unicode-ident" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der", - "spki", -] +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] -name = "proc-macro2" -version = "1.0.47" +name = "unicode-normalization" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ - "unicode-ident", + "tinyvec", ] [[package]] -name = "quote" -version = "1.0.21" +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] -name = "rand" -version = "0.5.6" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi", -] +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "rand_core" -version = "0.3.1" +name = "url" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ - "rand_core 0.4.2", + "form_urlencoded", + "idna", + "percent-encoding", ] [[package]] -name = "rand_core" -version = "0.4.2" +name = "uuid" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] -name = "rand_core" -version = "0.5.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "rand_core" -version = "0.6.4" +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ - "getrandom", + "same-file", + "winapi-util", ] [[package]] -name = "rfc6979" +name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", + "try-lock", ] [[package]] -name = "rlp" -version = "0.4.6" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73" -dependencies = [ - "rustc-hex", -] +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "rustc-hex" -version = "2.1.0" +name = "wasm-bindgen" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] [[package]] -name = "ryu" -version = "1.0.11" +name = "wasm-bindgen-backend" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-shared", +] [[package]] -name = "schemars" -version = "0.8.11" +name = "wasm-bindgen-futures" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "schemars_derive" -version = "0.8.11" +name = "wasm-bindgen-macro" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ - "proc-macro2", "quote", - "serde_derive_internals", - "syn", + "wasm-bindgen-macro-support", ] [[package]] -name = "sec1" -version = "0.3.0" +name = "wasm-bindgen-macro-support" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "proc-macro2", + "quote", + "syn 2.0.77", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "semver" -version = "1.0.14" +name = "wasm-bindgen-shared" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] -name = "serde" -version = "1.0.147" +name = "web-sys" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ - "serde_derive", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "serde-json-wasm" -version = "0.4.1" +name = "which" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ - "serde", + "either", + "home", + "once_cell", + "rustix", ] [[package]] -name = "serde_derive" -version = "1.0.147" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "proc-macro2", - "quote", - "syn", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "serde_derive_internals" -version = "0.26.0" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "serde_json" -version = "1.0.87" +name = "winapi-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "itoa", - "ryu", - "serde", + "windows-sys 0.59.0", ] [[package]] -name = "serde_repr" -version = "0.1.9" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "proc-macro2", - "quote", - "syn", + "windows-targets 0.48.5", ] [[package]] -name = "sha2" -version = "0.9.9" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "windows-targets 0.52.6", ] [[package]] -name = "sha2" -version = "0.10.6" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.6", + "windows-targets 0.52.6", ] [[package]] -name = "signature" -version = "1.6.4" +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "digest 0.10.6", - "rand_core 0.6.4", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] -name = "spki" -version = "0.6.0" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "base64ct", - "der", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] -name = "static_assertions" -version = "0.2.5" +name = "windows_aarch64_gnullvm" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "static_assertions" -version = "1.1.0" +name = "windows_aarch64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "subtle" -version = "2.4.1" +name = "windows_aarch64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "subtle-encoding" -version = "0.5.1" +name = "windows_aarch64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" -dependencies = [ - "zeroize", -] +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "syn" -version = "1.0.103" +name = "windows_i686_gnu" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] -name = "thiserror" -version = "1.0.37" +name = "windows_i686_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" -dependencies = [ - "thiserror-impl", -] +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "thiserror-impl" -version = "1.0.37" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "tiny-keccak" -version = "1.5.0" +name = "windows_i686_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" -dependencies = [ - "crunchy 0.2.2", -] +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] -name = "typenum" -version = "1.15.0" +name = "windows_i686_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "uint" -version = "0.5.0" +name = "windows_x86_64_gnu" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "082df6964410f6aa929a61ddfafc997e4f32c62c22490e439ac351cec827f436" -dependencies = [ - "byteorder", - "crunchy 0.2.2", - "heapsize", - "rustc-hex", -] +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] -name = "uint" -version = "0.9.4" +name = "windows_x86_64_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" -dependencies = [ - "byteorder", - "crunchy 0.2.2", - "hex", - "static_assertions 1.1.0", -] +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "unicode-ident" -version = "1.0.5" +name = "windows_x86_64_gnullvm" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "version_check" -version = "0.9.4" +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows_x86_64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "zerocopy-derive" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] [[package]] name = "zeroize" -version = "1.5.7" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[patch.unused]] +name = "injective-cosmwasm" +version = "0.1.74" +source = "git+https://github.com/InjectiveLabs/cw-injective.git?branch=dev#f0c00001f04ee004f9c97ecbe012127c7111bc44" diff --git a/Cargo.toml b/Cargo.toml index b1adc77..1f67ffb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,44 +1,59 @@ [workspace] -members = ["contracts/*"] +members = [ "contracts/*", "packages/*" ] +resolver = "2" [workspace.package] -version = "1.0.0" -authors = ["Antoni Mysliborski "] -edition = "2021" -license = "AGPL-v3-or-later" -homepage = "https://injectivelabs.org" -repository = "https://github.com/InjectiveLabs/cw20-adapter" +authors = [ "Injective Labs " ] documentation = "https://github.com/InjectiveLabs/cw20-adapter#readme" -keywords = ["blockchain", "cosmos", "cosmwasm", "injective"] -rust-version = "1.64.0" +edition = "2021" +homepage = "https://injectivelabs.org" +keywords = [ "blockchain", "cosmos", "cosmwasm", "injective" ] +license = "AGPL-v3-or-later" +repository = "https://github.com/InjectiveLabs/cw20-adapter" +rust-version = "1.78.0" +version = "2.0.0" [workspace.dependencies] -cosmwasm-schema = "1.1" -cosmwasm-std = "1.1" -cw2 = "0.16" -cw20 = "0.16.0" -cw-storage-plus = "0.16" -thiserror = "1.0" -cw-item-set = "0.6.0" -regex = "1.7.0" -injective-cosmwasm = "0.1.74" -anyhow = "1.0.66" -secp256k1 = "0.6.2" -rand = "0.4.6" -tiny-keccak = "1.2.1" -serde = "1.0.147" +anyhow = { version = "1.0.86" } +cosmwasm-schema = { version = "2.1.1" } +cosmwasm-std = { version = "2.1.0", features = [ "abort", "cosmwasm_1_2", "cosmwasm_1_3", "cosmwasm_1_4", "cosmwasm_2_0", "iterator", "stargate" ] } +cw-item-set = { version = "2.0.0" } +cw-storage-plus = { version = "2.0.0" } +cw2 = { version = "2.0.0" } +cw20 = { version = "2.0.0" } +cw20-base = { version = "2.0.0" } +enumset = { version = "1.1.5", features = [ "serde" ] } +injective-cosmwasm = { version = "0.3.0" } +injective-math = { version = "0.3.0" } +injective-std = { version = "1.13.0" } +injective-test-tube = { version = "1.13.2" } +injective-testing = { version = "1.1.2" } +prost = { version = "0.12.6" } +rand = { version = "0.4.6" } +regex = { version = "1.7.0" } +schemars = { version = "0.8.16", features = [ "enumset" ] } +secp256k1 = { version = "0.6.2" } +serde = { version = "1.0.193", default-features = false, features = [ "derive" ] } +serde-cw-value = { version = "0.7.0" } +serde-json-wasm = { version = "1.0.1" } +serde_json = { version = "1.0.120" } +thiserror = { version = "1.0.52" } +tiny-keccak = { version = "1.2.1" } + +# packages +testenv = { version = "0.1.0", path = "./packages/testenv" } [profile.release] -codegen-units = 1 -debug = false +codegen-units = 1 +debug = false debug-assertions = false -incremental = false -lto = true -opt-level = 3 -overflow-checks = true -rpath = false +incremental = false +lto = true +opt-level = 3 +overflow-checks = true +rpath = false [patch.crates-io] #injective-cosmwasm = { path = "../cw-injective/packages/injective-cosmwasm"} -injective-cosmwasm = { git = "https://github.com/InjectiveLabs/cw-injective.git", branch ="dev" } -#cw20-base = { path = "../cw-plus-inj/contracts/cw20-base" } \ No newline at end of file +injective-cosmwasm = { git = "https://github.com/InjectiveLabs/cw-injective.git", branch = "dev" } +#cw20-base = { path = "../cw-plus-inj/contracts/cw20-base" } diff --git a/build_release.sh b/build_release.sh index 9be7559..1998ab4 100755 --- a/build_release.sh +++ b/build_release.sh @@ -3,4 +3,4 @@ docker run --rm -v "$(pwd)":/code \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ - cosmwasm/workspace-optimizer:0.12.9 + cosmwasm/optimizer:0.16.0 diff --git a/contracts/cw20-adapter/Cargo.toml b/contracts/cw20-adapter/Cargo.toml index 27e60da..fae5419 100644 --- a/contracts/cw20-adapter/Cargo.toml +++ b/contracts/cw20-adapter/Cargo.toml @@ -1,32 +1,36 @@ [package] -name = "cw20-adapter" -description = "Description of the contract" -version = { workspace = true } -authors = { workspace = true } -edition = { workspace = true } -license = { workspace = true } -homepage = { workspace = true } -repository = { workspace = true } +authors = { workspace = true } +description = "Description of the contract" documentation = { workspace = true } -keywords = { workspace = true } -rust-version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +keywords = { workspace = true } +license = { workspace = true } +name = "cw20-adapter" +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } [lib] -crate-type = ["cdylib", "rlib"] +crate-type = [ "cdylib", "rlib" ] [features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all instantiate/execute/query exports -library = [] +library = [ ] [dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw2 = { workspace = true } -cw20 = { workspace = true } -cw-storage-plus = { workspace = true } -thiserror = { workspace = true } -cw-item-set = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-item-set = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw20 = { workspace = true } +cw20-base = { workspace = true } injective-cosmwasm = { workspace = true } -serde = { workspace = true } \ No newline at end of file +serde = { workspace = true } +thiserror = { workspace = true } + +[dev-dependencies] +injective-std = { workspace = true } +injective-test-tube = { workspace = true } +injective-testing = { workspace = true } +testenv = { workspace = true } diff --git a/contracts/cw20-adapter/src/contract.rs b/contracts/cw20-adapter/src/contract.rs index c4d8bb0..34ea901 100644 --- a/contracts/cw20-adapter/src/contract.rs +++ b/contracts/cw20-adapter/src/contract.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cosmwasm_std::{entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use injective_cosmwasm::{InjectiveMsgWrapper, InjectiveQueryWrapper}; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -37,7 +37,7 @@ pub fn execute( #[entry_point] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::RegisteredContracts {} => to_binary(&query::registered_contracts(deps)?), - QueryMsg::NewDenomFee {} => to_binary(&query::new_denom_fee(deps)?), + QueryMsg::RegisteredContracts {} => to_json_binary(&query::registered_contracts(deps)?), + QueryMsg::NewDenomFee {} => to_json_binary(&query::new_denom_fee(deps)?), } } diff --git a/contracts/cw20-adapter/src/execute_receive.rs b/contracts/cw20-adapter/src/execute_receive.rs index e05f757..63057ad 100644 --- a/contracts/cw20-adapter/src/execute_receive.rs +++ b/contracts/cw20-adapter/src/execute_receive.rs @@ -13,12 +13,16 @@ pub fn handle_on_received_cw20_funds_msg( if !info.funds.is_empty() { return Err(ContractError::SuperfluousFundsProvided); } + let mut response = Response::new(); + let token_contract = info.sender; + if !is_contract_registered(&deps, &token_contract) { ensure_sufficient_create_denom_balance(&deps, &env)?; response = response.add_message(register_contract_and_get_message(deps, &env, &token_contract)?); } + let master = env.contract.address; let denom = get_denom(&master, &token_contract); diff --git a/contracts/cw20-adapter/src/execute_redeem.rs b/contracts/cw20-adapter/src/execute_redeem.rs index a6161f9..12a4149 100644 --- a/contracts/cw20-adapter/src/execute_redeem.rs +++ b/contracts/cw20-adapter/src/execute_redeem.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{to_binary, Binary, DepsMut, Env, MessageInfo, Response, WasmMsg}; +use cosmwasm_std::{to_json_binary, Binary, DepsMut, Env, MessageInfo, Response, WasmMsg}; use cw20::Cw20ExecuteMsg; use injective_cosmwasm::{create_burn_tokens_msg, InjectiveMsgWrapper, InjectiveQueryWrapper}; @@ -26,16 +26,11 @@ pub fn handle_redeem_msg( Ok(denom) => Some(AdapterCoin { amount: c.amount, denom }), Err(_) => None, } - // if denom_parser.is_match(&c.denom) { - // Some(c.clone()) - // } else { - // None - // } }) .ok_or(ContractError::NoRegisteredTokensProvided)?; let cw20_addr = tokens_to_exchange.denom.cw20_addr.clone(); - // let cw20_addr = get_cw20_address_from_denom(&denom_parser, &tokens_to_exchange.denom).ok_or(ContractError::NoRegisteredTokensProvided)?; + let is_contract_registered = CW20_CONTRACTS.contains(deps.storage, &tokens_to_exchange.denom.cw20_addr); if !is_contract_registered { return Err(ContractError::NoRegisteredTokensProvided); @@ -46,7 +41,7 @@ pub fn handle_redeem_msg( let cw20_message: WasmMsg = match submessage { None => WasmMsg::Execute { contract_addr: cw20_addr, - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient, amount: tokens_to_exchange.amount, })?, @@ -54,7 +49,7 @@ pub fn handle_redeem_msg( }, Some(msg) => WasmMsg::Execute { contract_addr: cw20_addr, - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: recipient, amount: tokens_to_exchange.amount, msg, diff --git a/contracts/cw20-adapter/src/lib.rs b/contracts/cw20-adapter/src/lib.rs index f1bc920..6af7472 100644 --- a/contracts/cw20-adapter/src/lib.rs +++ b/contracts/cw20-adapter/src/lib.rs @@ -8,3 +8,6 @@ pub mod execute_register; pub mod msg; pub mod query; pub mod state; + +#[cfg(test)] +mod testing; diff --git a/contracts/cw20-adapter/tests/common/mod.rs b/contracts/cw20-adapter/src/testing/common/mod.rs similarity index 100% rename from contracts/cw20-adapter/tests/common/mod.rs rename to contracts/cw20-adapter/src/testing/common/mod.rs diff --git a/contracts/cw20-adapter/src/testing/instantiation.rs b/contracts/cw20-adapter/src/testing/instantiation.rs new file mode 100644 index 0000000..6321d64 --- /dev/null +++ b/contracts/cw20-adapter/src/testing/instantiation.rs @@ -0,0 +1,41 @@ +use crate::msg::InstantiateMsg; + +use injective_test_tube::{Account, Module, Wasm}; +use injective_testing::test_tube::utils::store_code; +use testenv::utils::Setup; + +#[test] +fn test_instantiation() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + + let res = wasm + .instantiate( + code_id, + &InstantiateMsg {}, + Some(&env.owner.address()), + Some("cw20-adaptor-contract"), + &[], + &env.owner, + ) + .unwrap(); + + let attributes = res + .events + .iter() + .find(|e| e.ty == "cosmwasm.wasm.v1.EventContractInstantiated") + .unwrap() + .attributes + .clone(); + + let admin = attributes.iter().find(|e| e.key == "admin").unwrap(); + let creator = attributes.iter().find(|e| e.key == "creator").unwrap(); + let label = attributes.iter().find(|e| e.key == "label").unwrap(); + + assert_eq!(admin.value, format!("\"{}\"", env.owner.address())); + assert_eq!(creator.value, format!("\"{}\"", env.owner.address())); + assert_eq!(label.value, format!("\"{}\"", "cw20-adaptor-contract")); +} diff --git a/contracts/cw20-adapter/src/testing/mod.rs b/contracts/cw20-adapter/src/testing/mod.rs new file mode 100644 index 0000000..89e2f53 --- /dev/null +++ b/contracts/cw20-adapter/src/testing/mod.rs @@ -0,0 +1,6 @@ +mod instantiation; +mod query; +mod receive; +mod redeem; +mod register; +mod utils; diff --git a/contracts/cw20-adapter/src/testing/query.rs b/contracts/cw20-adapter/src/testing/query.rs new file mode 100644 index 0000000..a85d27a --- /dev/null +++ b/contracts/cw20-adapter/src/testing/query.rs @@ -0,0 +1,29 @@ +use crate::testing::utils::{instantiate, query_new_denom_fee, query_register_contract}; + +use cosmwasm_std::Coin; +use injective_test_tube::{Module, Wasm}; +use injective_testing::test_tube::utils::store_code; +use testenv::utils::Setup; + +#[test] +fn test_queries() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + + let address = instantiate(&env.app, &env.owner, code_id, "cw20-adapter"); + + let res = query_register_contract(&env.app, &address).unwrap(); + assert!(res.is_empty()); + + let res = query_new_denom_fee(&env.app, &address).unwrap(); + assert_eq!( + res, + vec![Coin { + amount: 10_000_000_000_000_000_000u128.into(), + denom: "inj".to_string() + }] + ); +} diff --git a/contracts/cw20-adapter/src/testing/receive.rs b/contracts/cw20-adapter/src/testing/receive.rs new file mode 100644 index 0000000..84a80e7 --- /dev/null +++ b/contracts/cw20-adapter/src/testing/receive.rs @@ -0,0 +1,72 @@ +use crate::testing::utils::{assert_execute_error, instantiate, instantiate_cw20, mint_cw20, register_contract, send_cw20, store_code_with_path}; + +use cosmwasm_std::{coins, Uint128}; +use injective_test_tube::{Account, Module, Wasm}; +use injective_testing::test_tube::utils::store_code; +use testenv::utils::Setup; + +use super::utils::query_balance_cw20; + +#[test] +fn test_receive() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_000u128, "inj"); + register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap(); + + let mint_amount = Uint128::from(2_000_000u128); + mint_cw20(&env.app, &env.owner, &cw20_addr, mint_amount, env.traders[0].account.address()).unwrap(); + + let adaptor_balance_before = query_balance_cw20(&env.app, &cw20_addr, adaptor_addr.clone()).unwrap(); + assert!(adaptor_balance_before.balance.is_zero()); + + send_cw20(&env.app, &env.traders[0].account, &cw20_addr, adaptor_addr.clone(), mint_amount).unwrap(); + + let adaptor_balance_after = query_balance_cw20(&env.app, &cw20_addr, adaptor_addr.clone()).unwrap(); + assert_eq!(adaptor_balance_after.balance, mint_amount); + + let trader_balance = env.get_balance(env.traders[0].account.address(), format!("factory/{}/{}", adaptor_addr, cw20_addr)); + assert_eq!(trader_balance, mint_amount); +} + +#[test] +fn test_fail_receive_not_registered() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let mint_amount = Uint128::from(2_000_000u128); + mint_cw20(&env.app, &env.owner, &cw20_addr, mint_amount, env.traders[0].account.address()).unwrap(); + + let adaptor_balance_before = query_balance_cw20(&env.app, &cw20_addr, adaptor_addr.clone()).unwrap(); + assert!(adaptor_balance_before.balance.is_zero()); + + let err = send_cw20(&env.app, &env.traders[0].account, &cw20_addr, adaptor_addr.clone(), mint_amount).unwrap_err(); + + assert_eq!( + err.to_string(), + assert_execute_error("dispatch: submessages: Adapter is missing balance to create a new token-factory denom") + ); +} diff --git a/contracts/cw20-adapter/src/testing/redeem.rs b/contracts/cw20-adapter/src/testing/redeem.rs new file mode 100644 index 0000000..6b1c718 --- /dev/null +++ b/contracts/cw20-adapter/src/testing/redeem.rs @@ -0,0 +1,89 @@ +use crate::testing::utils::{instantiate, instantiate_cw20, mint_cw20, redeem_and_transfer, register_contract, send_cw20, store_code_with_path}; + +use cosmwasm_std::{coins, Uint128}; +use injective_test_tube::{Account, Module, Wasm}; +use injective_testing::test_tube::utils::store_code; +use testenv::utils::Setup; + +use super::utils::query_balance_cw20; + +#[test] +fn test_redeem() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_000u128, "inj"); + register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap(); + + let mint_amount = Uint128::from(2_000_000u128); + mint_cw20(&env.app, &env.owner, &cw20_addr, mint_amount, env.traders[0].account.address()).unwrap(); + + send_cw20(&env.app, &env.traders[0].account, &cw20_addr, adaptor_addr.clone(), mint_amount).unwrap(); + + let funds = coins(mint_amount.into(), format!("factory/{}/{}", adaptor_addr, cw20_addr.clone())); + redeem_and_transfer(&env.app, &env.traders[0].account, &adaptor_addr, None, funds).unwrap(); + + let trader_balance = env.get_balance( + env.traders[0].account.address(), + format!("factory/{}/{}", adaptor_addr, cw20_addr.clone()), + ); + assert!(trader_balance.is_zero()); + + let recipient_balance = query_balance_cw20(&env.app, &cw20_addr.clone(), env.traders[0].account.address()).unwrap(); + assert_eq!(recipient_balance.balance, mint_amount); +} + +#[test] +fn test_redeem_and_transfer() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_000u128, "inj"); + register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap(); + + let mint_amount = Uint128::from(2_000_000u128); + mint_cw20(&env.app, &env.owner, &cw20_addr, mint_amount, env.traders[0].account.address()).unwrap(); + + send_cw20(&env.app, &env.traders[0].account, &cw20_addr, adaptor_addr.clone(), mint_amount).unwrap(); + + let funds = coins(mint_amount.into(), format!("factory/{}/{}", adaptor_addr, cw20_addr.clone())); + redeem_and_transfer( + &env.app, + &env.traders[0].account, + &adaptor_addr, + Some(env.traders[6].account.address()), + funds, + ) + .unwrap(); + + let trader_balance = env.get_balance( + env.traders[0].account.address(), + format!("factory/{}/{}", adaptor_addr, cw20_addr.clone()), + ); + assert!(trader_balance.is_zero()); + + let recipient_balance = query_balance_cw20(&env.app, &cw20_addr.clone(), env.traders[6].account.address()).unwrap(); + assert_eq!(recipient_balance.balance, mint_amount); +} diff --git a/contracts/cw20-adapter/src/testing/register.rs b/contracts/cw20-adapter/src/testing/register.rs new file mode 100644 index 0000000..5cf185d --- /dev/null +++ b/contracts/cw20-adapter/src/testing/register.rs @@ -0,0 +1,134 @@ +use crate::{ + error::ContractError, + testing::utils::{assert_execute_error, instantiate, instantiate_cw20, query_register_contract, register_contract, store_code_with_path}, +}; + +use cosmwasm_std::coins; +use injective_test_tube::{Module, Wasm}; +use injective_testing::{mocks::MOCK_ATOM_DENOM, test_tube::utils::store_code}; +use testenv::utils::Setup; + +#[test] +fn test_register() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_000u128, "inj"); + register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap(); + + let res = query_register_contract(&env.app, &adaptor_addr).unwrap(); + assert_eq!(res, vec![cw20_addr.to_string()]); +} + +#[test] +fn test_register_additional_funds() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_001u128, "inj"); + let err = register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap_err(); + + assert_eq!( + err.to_string(), + assert_execute_error(&ContractError::SuperfluousFundsProvided.to_string()) + ); +} + +#[test] +fn test_register_twice() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(10_000_000_000_000_000_000u128, "inj"); + register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit.clone()).unwrap(); + + let err = register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap_err(); + + assert_eq!( + err.to_string(), + assert_execute_error("CW-20 contract with the same address was already registered") + ); +} + +#[test] +fn test_register_insufficient_funds() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(9_999_999_999_999_999_999u128, "inj"); + let err = register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap_err(); + + assert_eq!( + err.to_string(), + assert_execute_error("Adapter is missing balance to create a new token-factory denom") + ); +} + +#[test] +fn test_register_invalid_funds() { + let env = Setup::new(); + + let wasm = Wasm::new(&env.app); + + let adaptor_code_id = store_code(&wasm, &env.owner, "cw20_adapter".to_string()); + let base_code_id = store_code_with_path( + &wasm, + &env.owner, + "../../contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm".to_string(), + ); + + let adaptor_addr = instantiate(&env.app, &env.owner, adaptor_code_id, "cw20-adapter"); + let cw20_addr = instantiate_cw20(&env.app, &env.owner, base_code_id, "cw20-base", "cw20-mofo"); + + let deposit = coins(1_000_000u128, MOCK_ATOM_DENOM); + let err = register_contract(&env.app, &env.owner, &adaptor_addr, &cw20_addr, deposit).unwrap_err(); + + assert_eq!( + err.to_string(), + assert_execute_error("Adapter is missing balance to create a new token-factory denom") + ); +} diff --git a/contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm b/contracts/cw20-adapter/src/testing/test_artifacts/cw20_base.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5487e388cc2fd7d69a3bd32a3c56cd9c47b73414 GIT binary patch literal 269740 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 I+g6_b4~yX(6951J literal 0 HcmV?d00001 diff --git a/contracts/cw20-adapter/src/testing/utils.rs b/contracts/cw20-adapter/src/testing/utils.rs new file mode 100644 index 0000000..24b18c4 --- /dev/null +++ b/contracts/cw20-adapter/src/testing/utils.rs @@ -0,0 +1,142 @@ +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Binary, Coin, Uint128}; +use cw20::{BalanceResponse, Cw20Coin, MinterResponse}; +use cw20_base::msg::{ExecuteMsg as Cw20ExecuteMsg, InstantiateMarketingInfo, QueryMsg as Cw20QueryMsg}; +use injective_test_tube::{ + injective_std::types::cosmwasm::wasm::v1::MsgExecuteContractResponse, Account, InjectiveTestApp, Module, RunnerExecuteResult, RunnerResult, + SigningAccount, Wasm, +}; + +#[cw_serde] +pub struct Cw20InstantiateMsg { + pub name: String, + pub symbol: String, + pub decimals: u8, + pub initial_balances: Vec, + pub mint: Option, + pub marketing: Option, +} + +pub fn assert_execute_error(message: &str) -> String { + format!( + "execute error: failed to execute message; message index: 0: {}: execute wasm contract failed", + message + ) +} + +pub fn store_code_with_path(wasm: &Wasm, owner: &SigningAccount, path: String) -> u64 { + let wasm_byte_code = std::fs::read(path).unwrap(); + wasm.store_code(&wasm_byte_code, None, owner).unwrap().data.code_id +} + +pub fn instantiate(app: &InjectiveTestApp, owner: &SigningAccount, code_id: u64, label: &str) -> String { + let wasm = Wasm::new(app); + + wasm.instantiate(code_id, &InstantiateMsg {}, Some(&owner.address()), Some(label), &[], owner) + .unwrap() + .data + .address +} + +pub fn instantiate_cw20(app: &InjectiveTestApp, owner: &SigningAccount, code_id: u64, label: &str, name: &str) -> String { + let wasm = Wasm::new(app); + + wasm.instantiate( + code_id, + &Cw20InstantiateMsg { + name: name.to_string(), + symbol: "ERC".to_string(), + decimals: 6, + initial_balances: vec![], + mint: Some(MinterResponse { + minter: owner.address().to_string(), + cap: None, + }), + marketing: None, + }, + Some(&owner.address()), + Some(label), + &[], + owner, + ) + .unwrap() + .data + .address +} + +pub fn mint_cw20( + app: &InjectiveTestApp, + owner: &SigningAccount, + contract: &str, + amount: Uint128, + recipient: String, +) -> RunnerExecuteResult { + let wasm = Wasm::new(app); + + wasm.execute(contract, &Cw20ExecuteMsg::Mint { recipient, amount }, &[], owner) +} + +pub fn send_cw20( + app: &InjectiveTestApp, + owner: &SigningAccount, + contract: &str, + recipient: String, + amount: Uint128, +) -> RunnerExecuteResult { + let wasm = Wasm::new(app); + + wasm.execute( + contract, + &Cw20ExecuteMsg::Send { + contract: recipient, + amount, + msg: Binary::default(), + }, + &[], + owner, + ) +} + +pub fn register_contract( + app: &InjectiveTestApp, + owner: &SigningAccount, + contract: &str, + addr: &str, + funds: Vec, +) -> RunnerExecuteResult { + let wasm = Wasm::new(app); + + wasm.execute(contract, &ExecuteMsg::RegisterCw20Contract { addr: Addr::unchecked(addr) }, &funds, owner) +} + +pub fn redeem_and_transfer( + app: &InjectiveTestApp, + owner: &SigningAccount, + contract: &str, + recipient: Option, + funds: Vec, +) -> RunnerExecuteResult { + let wasm = Wasm::new(app); + + wasm.execute(contract, &ExecuteMsg::RedeemAndTransfer { recipient }, &funds, owner) +} + +pub fn query_register_contract(app: &InjectiveTestApp, contract: &str) -> RunnerResult> { + let wasm = Wasm::new(app); + + wasm.query(contract, &QueryMsg::RegisteredContracts {}) +} + +pub fn query_new_denom_fee(app: &InjectiveTestApp, contract: &str) -> RunnerResult> { + let wasm = Wasm::new(app); + + wasm.query(contract, &QueryMsg::NewDenomFee {}) +} + +pub fn query_balance_cw20(app: &InjectiveTestApp, contract: &str, address: String) -> RunnerResult { + let wasm = Wasm::new(app); + + wasm.query(contract, &Cw20QueryMsg::Balance { address }) +} diff --git a/contracts/cw20-adapter/tests/execute_metadata_tests.rs b/contracts/cw20-adapter/tests/execute_metadata_tests.rs deleted file mode 100644 index aef9d21..0000000 --- a/contracts/cw20-adapter/tests/execute_metadata_tests.rs +++ /dev/null @@ -1,63 +0,0 @@ -mod common; - -use cosmwasm_std::testing::mock_env; -use cosmwasm_std::{Addr, CosmosMsg, SubMsg}; -use cw20_adapter::common::get_denom; -use cw20_adapter::error::ContractError; -use cw20_adapter::execute_metadata::handle_update_metadata; -use cw20_adapter::state::CW20_CONTRACTS; -use injective_cosmwasm::{mock_dependencies, InjectiveMsg, InjectiveMsgWrapper, InjectiveRoute, WasmMockQuerier}; - -use crate::common::{create_cw20_info_query_handler, CONTRACT_ADDRESS, CW_20_ADDRESS}; - -#[test] -fn it_updates_metadata() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - smart_query_handler: create_cw20_info_query_handler(), - ..Default::default() - }; - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - CW20_CONTRACTS.insert(&mut deps.storage, CW_20_ADDRESS).unwrap(); - - let response = handle_update_metadata(deps.as_mut(), env, Addr::unchecked(CW_20_ADDRESS)).unwrap(); - assert_eq!(response.messages.len(), 1, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.get(0).unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::SetTokenMetadata { - denom, - name, - symbol, - decimals, - } = msg_data - { - assert_eq!( - get_denom(&Addr::unchecked(CONTRACT_ADDRESS), &Addr::unchecked(CW_20_ADDRESS)), - denom.as_str(), - "incorrect denom in set metadata message" - ); - assert_eq!("SOL", symbol.as_str(), "incorrect symbol in set metadata message"); - assert_eq!("Solana", name.as_str(), "incorrect name in set metadata message"); - assert_eq!(6, *decimals, "incorrect decimals in set metadata message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} - -#[test] -fn it_tries_to_update_not_registered_contract() { - let mut deps = mock_dependencies(); - let env = mock_env(); - - let err_response = handle_update_metadata(deps.as_mut(), env, Addr::unchecked(CW_20_ADDRESS)).unwrap_err(); - assert_eq!(err_response, ContractError::ContractNotRegistered, "incorrect error"); -} diff --git a/contracts/cw20-adapter/tests/execute_receive_tests.rs b/contracts/cw20-adapter/tests/execute_receive_tests.rs deleted file mode 100644 index 9879671..0000000 --- a/contracts/cw20-adapter/tests/execute_receive_tests.rs +++ /dev/null @@ -1,152 +0,0 @@ -mod common; - -use cosmwasm_std::{ - testing::{mock_env, mock_info}, - Addr, Coin, CosmosMsg, SubMsg, Uint128, -}; - -use cw20_adapter::{error::ContractError, execute_receive::handle_on_received_cw20_funds_msg, state::CW20_CONTRACTS}; -use injective_cosmwasm::{mock_dependencies, InjectiveMsg, InjectiveMsgWrapper, InjectiveRoute, WasmMockQuerier}; - -use crate::common::{create_custom_bank_balance_query_handler, create_cw20_info_query_handler, CONTRACT_ADDRESS, CW_20_ADDRESS, SENDER}; - -#[test] -fn it_handles_receive_correctly_if_not_already_registered() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - balance_query_handler: create_custom_bank_balance_query_handler(Coin::new(10, "inj")), - smart_query_handler: create_cw20_info_query_handler(), - ..Default::default() - }; - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - let amount_to_send = Uint128::new(100); - let response = handle_on_received_cw20_funds_msg(deps.as_mut(), env, mock_info(CW_20_ADDRESS, &[]), SENDER.to_string(), amount_to_send).unwrap(); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(contract_registered, "contract wasn't registered"); - - assert_eq!(response.messages.len(), 2, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.first().unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::CreateDenom { sender, subdenom } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the create denom message"); - assert_eq!(CW_20_ADDRESS, subdenom.as_str(), "incorrect subdenom in the create denom message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.get(1).unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::Mint { sender, amount, mint_to } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the mint message"); - assert_eq!(amount_to_send, amount.amount, "incorrect amount in the mint message"); - assert_eq!( - format!("factory/{}/{}", CONTRACT_ADDRESS, CW_20_ADDRESS), - amount.denom, - "incorrect amount in the mint message" - ); - assert_eq!(SENDER, mint_to, "incorrect mint_to in the mint message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} - -#[test] -fn it_handles_receive_correctly_if_already_registered() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - balance_query_handler: create_custom_bank_balance_query_handler(Coin::new(10, "inj")), - ..Default::default() - }; - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - CW20_CONTRACTS.insert(&mut deps.storage, CW_20_ADDRESS).unwrap(); - let amount_to_send = Uint128::new(100); - let response = handle_on_received_cw20_funds_msg(deps.as_mut(), env, mock_info(CW_20_ADDRESS, &[]), SENDER.to_string(), amount_to_send).unwrap(); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(contract_registered, "contract wasn't registered"); - - assert_eq!(response.messages.len(), 1, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.first().unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::Mint { sender, amount, mint_to } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the mint message"); - assert_eq!(amount_to_send, amount.amount, "incorrect amount in the mint message"); - assert_eq!( - format!("factory/{}/{}", CONTRACT_ADDRESS, CW_20_ADDRESS), - amount.denom, - "incorrect amount in the mint message" - ); - assert_eq!(SENDER, mint_to, "incorrect mint_to in the mint message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} - -#[test] -fn it_returns_error_on_receive_if_contract_not_registered_and_contract_has_insufficient_balance() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - balance_query_handler: create_custom_bank_balance_query_handler(Coin::new(9, "inj")), - ..Default::default() - }; - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - let amount_to_send = Uint128::new(100); - let response = - handle_on_received_cw20_funds_msg(deps.as_mut(), env, mock_info(CW_20_ADDRESS, &[]), SENDER.to_string(), amount_to_send).unwrap_err(); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); - - assert_eq!(response, ContractError::NotEnoughBalanceToPayDenomCreationFee, "incorrect error returned"); -} - -#[test] -fn it_returns_error_on_receive_if_additional_funds_are_provided() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - balance_query_handler: create_custom_bank_balance_query_handler(Coin::new(10, "inj")), - ..Default::default() - }; - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - let amount_to_send = Uint128::new(100); - let response = handle_on_received_cw20_funds_msg( - deps.as_mut(), - env, - mock_info(CW_20_ADDRESS, &[Coin::new(1000, "usdt")]), - SENDER.to_string(), - amount_to_send, - ) - .unwrap_err(); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); - assert_eq!(response, ContractError::SuperfluousFundsProvided, "funds were provided"); -} diff --git a/contracts/cw20-adapter/tests/execute_redeem_tests.rs b/contracts/cw20-adapter/tests/execute_redeem_tests.rs deleted file mode 100644 index b1784df..0000000 --- a/contracts/cw20-adapter/tests/execute_redeem_tests.rs +++ /dev/null @@ -1,170 +0,0 @@ -use cosmwasm_std::{ - from_binary, - testing::{mock_env, mock_info}, - to_binary, Addr, Coin, CosmosMsg, SubMsg, WasmMsg, -}; -use cw20::Cw20ExecuteMsg; -use cw20_adapter::{error::ContractError, execute_redeem::handle_redeem_msg, state::CW20_CONTRACTS}; -use injective_cosmwasm::{mock_dependencies, InjectiveMsg, InjectiveMsgWrapper, InjectiveRoute}; - -use crate::common::{CONTRACT_ADDRESS, CW_20_ADDRESS, SENDER}; - -mod common; - -#[test] -fn it_handles_redeem_and_transfer_correctly() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - CW20_CONTRACTS.insert(&mut deps.storage, CW_20_ADDRESS).unwrap(); - - let coins_to_burn = Coin::new(10, format!("factory/{}/{}", CONTRACT_ADDRESS, CW_20_ADDRESS)); - let response = handle_redeem_msg( - deps.as_mut(), - env, - mock_info(CW_20_ADDRESS, &[coins_to_burn.clone()]), - Some(SENDER.to_string()), - None, - ) - .unwrap(); - - assert_eq!(response.messages.len(), 2, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Wasm(WasmMsg::Execute { contract_addr, msg, funds }), - .. - } = response.messages.first().unwrap() - { - let expected_coins: Vec = vec![]; - assert_eq!(&expected_coins, funds, "incorrect funds found in execute message"); - assert_eq!(CW_20_ADDRESS, contract_addr, "incorrect contact_addr in execute message"); - - let deserialised_msg: Cw20ExecuteMsg = from_binary(msg).unwrap(); - - if let Cw20ExecuteMsg::Transfer { recipient, amount } = deserialised_msg { - assert_eq!(SENDER, recipient.as_str(), "incorrect recipient in the transfer message"); - assert_eq!(coins_to_burn.amount, amount, "incorrect amount in the transfer message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.get(1).unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::Burn { sender, amount } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the create denom message"); - assert_eq!(&coins_to_burn, amount, "incorrect amount in the burn message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} - -#[test] -fn it_returns_error_if_redeeming_non_factory_token() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - - let response = handle_redeem_msg( - deps.as_mut(), - env, - mock_info(CW_20_ADDRESS, &[Coin::new(10, "usdt")]), - Some(SENDER.to_string()), - None, - ) - .unwrap_err(); - assert_eq!(response, ContractError::NoRegisteredTokensProvided, "incorrect error returned") -} - -#[test] -fn it_returns_error_if_redeeming_zero_tokens() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - - let response = handle_redeem_msg(deps.as_mut(), env, mock_info(CW_20_ADDRESS, &[]), Some(SENDER.to_string()), None).unwrap_err(); - assert_eq!(response, ContractError::NoRegisteredTokensProvided, "incorrect error returned") -} - -#[test] -fn it_returns_error_if_redeeming_unknown_factory_token() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - - let response = handle_redeem_msg( - deps.as_mut(), - env, - mock_info(CW_20_ADDRESS, &[Coin::new(10, format!("factory/{}/{}", CONTRACT_ADDRESS, CW_20_ADDRESS))]), - Some(SENDER.to_string()), - None, - ) - .unwrap_err(); - assert_eq!(response, ContractError::NoRegisteredTokensProvided, "incorrect error returned") -} - -#[test] -fn it_handles_redeem_and_send_correctly() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - CW20_CONTRACTS.insert(&mut deps.storage, CW_20_ADDRESS).unwrap(); - - let coins_to_burn = Coin::new(10, format!("factory/{}/{}", CONTRACT_ADDRESS, CW_20_ADDRESS)); - let response = handle_redeem_msg( - deps.as_mut(), - env, - mock_info(CW_20_ADDRESS, &[coins_to_burn.clone()]), - Some(CW_20_ADDRESS.to_string()), - Some(to_binary(&coins_to_burn).unwrap()), // doesn't matter what is the message - ) - .unwrap(); - - assert_eq!(response.messages.len(), 2, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Wasm(WasmMsg::Execute { contract_addr, msg, funds }), - .. - } = response.messages.first().unwrap() - { - let expected_coins: Vec = vec![]; - assert_eq!(&expected_coins, funds, "incorrect funds found in execute message"); - assert_eq!(CW_20_ADDRESS, contract_addr, "incorrect contact_addr in execute message"); - - let deserialised_msg: Cw20ExecuteMsg = from_binary(msg).unwrap(); - - if let Cw20ExecuteMsg::Send { contract, amount, .. } = deserialised_msg { - assert_eq!(CW_20_ADDRESS, contract.as_str(), "incorrect recipient in the transfer message"); - assert_eq!(coins_to_burn.amount, amount, "incorrect amount in the transfer message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.get(1).unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::Burn { sender, amount } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the create denom message"); - assert_eq!(&coins_to_burn, amount, "incorrect amount in the burn message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} diff --git a/contracts/cw20-adapter/tests/execute_register_tests.rs b/contracts/cw20-adapter/tests/execute_register_tests.rs deleted file mode 100644 index 23351fc..0000000 --- a/contracts/cw20-adapter/tests/execute_register_tests.rs +++ /dev/null @@ -1,201 +0,0 @@ -use cosmwasm_std::{ - testing::{mock_env, mock_info}, - Addr, Coin, CosmosMsg, SubMsg, -}; - -use cw20_adapter::{error::ContractError, execute_register::handle_register_msg, state::CW20_CONTRACTS}; -use injective_cosmwasm::{mock_dependencies, InjectiveMsg, InjectiveMsgWrapper, InjectiveRoute, WasmMockQuerier}; - -use common::{create_cw20_failing_info_query_handler, create_cw20_info_query_handler, create_denom_creation_fee_failing_handler}; - -use crate::common::{CONTRACT_ADDRESS, CW_20_ADDRESS, SENDER}; - -mod common; - -// const CONTRACT_ADDRESS: &str = "inj1pvrwmjuusn9wh34j7y520g8gumuy9xtlt6xtzw"; -// const CW_20_ADDRESS: &str = "inj1pjcw9hhx8kf462qtgu37p7l7shyqgpfr82r6em"; -// const SENDER: &str = "inj1n0qvel0zfmsxu3q8q23xzjvuwfxn0ydlhgyh7h"; - -#[test] -fn it_handles_correct_register_msg_with_exact_funds() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - smart_query_handler: create_cw20_info_query_handler(), - ..Default::default() - }; - - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - let response = handle_register_msg( - deps.as_mut(), - env, - mock_info(SENDER, &[Coin::new(10, "inj")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap(); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(contract_registered, "contract wasn't registered"); - - assert_eq!(response.messages.len(), 1, "incorrect number of messages returned"); - - if let SubMsg { - msg: CosmosMsg::Custom(InjectiveMsgWrapper { route, msg_data }), - .. - } = response.messages.first().unwrap() - { - assert_eq!(route, &InjectiveRoute::Tokenfactory, "submessage had wrong route"); - if let InjectiveMsg::CreateDenom { sender, subdenom } = msg_data { - assert_eq!(CONTRACT_ADDRESS, sender.as_str(), "incorrect sender in the create denom message"); - assert_eq!(CW_20_ADDRESS, subdenom.as_str(), "incorrect subdenom in the create denom message"); - } else { - panic!("incorrect injective message found") - } - } else { - panic!("incorrect submessage type found") - } -} - -#[test] -fn it_handles_correct_register_msg_with_extra_funds() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - env.contract.address = Addr::unchecked(CONTRACT_ADDRESS); - let response_err = handle_register_msg( - deps.as_mut(), - env, - mock_info(SENDER, &[Coin::new(100, "inj"), Coin::new(20, "usdt")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap_err(); - assert_eq!(response_err, ContractError::SuperfluousFundsProvided); -} - -#[test] -fn it_handles_correct_register_msg_with_non_cannonical_cw20_address() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - smart_query_handler: create_cw20_failing_info_query_handler(), - ..Default::default() - }; - - let non_cannonical_address = "stefan"; - let response = handle_register_msg( - deps.as_mut(), - mock_env(), - mock_info(SENDER, &[Coin::new(10, "inj")]), - Addr::unchecked(non_cannonical_address.to_string()), - ) - .unwrap_err(); - - assert_eq!(ContractError::NotCw20Address, response, "should fail with wrong cw-20 address"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, non_cannonical_address); - assert!(!contract_registered, "contract was registered"); -} - -#[test] -fn it_returns_error_if_already_registered_register_msg() { - let mut deps = mock_dependencies(); - let storage = &mut deps.storage; - let contract_address = Addr::unchecked("amazing_address"); - CW20_CONTRACTS.insert(storage, contract_address.as_str()).unwrap(); - - let response = handle_register_msg(deps.as_mut(), mock_env(), mock_info("sender", &[]), contract_address); - - assert_eq!( - response.unwrap_err(), - ContractError::ContractAlreadyRegistered, - "incorrect error returned" - ) -} - -#[test] -fn it_returns_error_if_cannot_query_denom_creation_fee_register_msg() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - token_factory_denom_creation_fee_handler: create_denom_creation_fee_failing_handler(), - ..Default::default() - }; - - let response = handle_register_msg( - deps.as_mut(), - mock_env(), - mock_info(SENDER, &[Coin::new(10, "inj")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap_err(); - - assert!(response.to_string().contains("custom error"), "incorrect error returned"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); -} - -#[test] -fn it_returns_error_if_mismatched_denom_is_passed_register_msg() { - let mut deps = mock_dependencies(); - let response = handle_register_msg( - deps.as_mut(), - mock_env(), - mock_info(SENDER, &[Coin::new(10, "usdt")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap_err(); - - assert_eq!(response, ContractError::NotEnoughBalanceToPayDenomCreationFee, "incorrect error returned"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); -} - -#[test] -fn it_returns_error_if_insufficient_coins_are_passed_register_msg() { - let mut deps = mock_dependencies(); - - let response = handle_register_msg( - deps.as_mut(), - mock_env(), - mock_info(SENDER, &[Coin::new(9, "inj")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap_err(); - - assert_eq!(response, ContractError::NotEnoughBalanceToPayDenomCreationFee, "incorrect error returned"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); -} - -#[test] -fn it_returns_error_if_no_coins_are_passed_register_msg() { - let mut deps = mock_dependencies(); - let response = handle_register_msg(deps.as_mut(), mock_env(), mock_info(SENDER, &[]), Addr::unchecked(CW_20_ADDRESS)).unwrap_err(); - - assert_eq!(response, ContractError::NotEnoughBalanceToPayDenomCreationFee, "incorrect error returned"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); -} - -#[test] -fn it_returns_error_if_register_is_not_cw20_msg() { - let mut deps = mock_dependencies(); - deps.querier = WasmMockQuerier { - smart_query_handler: create_cw20_failing_info_query_handler(), - ..Default::default() - }; - - let response = handle_register_msg( - deps.as_mut(), - mock_env(), - mock_info(SENDER, &[Coin::new(10, "inj")]), - Addr::unchecked(CW_20_ADDRESS), - ) - .unwrap_err(); - - assert_eq!(response, ContractError::NotCw20Address, "incorrect error returned"); - - let contract_registered = CW20_CONTRACTS.contains(&deps.storage, CW_20_ADDRESS); - assert!(!contract_registered, "contract was registered"); -} diff --git a/contracts/cw20-adapter/tests/integration_test.rs b/contracts/cw20-adapter/tests/integration_test.rs deleted file mode 100644 index d0b6b66..0000000 --- a/contracts/cw20-adapter/tests/integration_test.rs +++ /dev/null @@ -1,48 +0,0 @@ -mod common; - -use cosmwasm_std::testing::mock_info; -use cosmwasm_std::{Addr, Coin, Uint128}; -use cw20_adapter::common::get_denom; -use injective_cosmwasm::{create_simple_balance_bank_query_handler, mock_dependencies, WasmMockQuerier}; - -use cw20_adapter::contract::{execute, instantiate}; -use cw20_adapter::msg::{ExecuteMsg, InstantiateMsg}; - -use crate::common::{create_cw20_info_query_handler, mock_env}; - -pub const ADAPTER_CONTRACT: &str = "inj1zwv6feuzhy6a9wekh96cd57lsarmqlwxvdl4nk"; -pub const CW20_CONTRACT: &str = "inj1h0y3hssxf4vsdacfmjg720642cvpxwyqh35kpn"; -pub const ADMIN: &str = "inj1qg5ega6dykkxc307y25pecuufrjkxkag6xhp6y"; -pub const USER: &str = "inj1gfawuv6fslzjlfa4v7exv27mk6rpfeyv823eu2"; - -#[test] -fn it_can_perform_basic_operations() { - let mut deps = mock_dependencies(); - let mut wasm_querier = WasmMockQuerier::new(); - - wasm_querier.balance_query_handler = create_simple_balance_bank_query_handler(vec![Coin::new(10, "inj")]); - wasm_querier.smart_query_handler = create_cw20_info_query_handler(); - deps.querier = wasm_querier; - - let msg = InstantiateMsg {}; - - let info_inst = mock_info(ADMIN, &[]); - let _res_inst = instantiate(deps.as_mut(), mock_env(ADAPTER_CONTRACT), info_inst, msg).unwrap(); - - // send some tokens to a contract - let info_receive = mock_info(CW20_CONTRACT, &[]); - let msg = ExecuteMsg::Receive { - sender: USER.to_string(), - amount: Uint128::new(1000), - msg: Default::default(), - }; - let _res_receive = execute(deps.as_mut(), mock_env(ADAPTER_CONTRACT), info_receive, msg).unwrap(); - - let denom = get_denom(&Addr::unchecked(ADAPTER_CONTRACT), &Addr::unchecked(CW20_CONTRACT)); - // redeem some tokens to a contract - let info_redeem = mock_info(USER, &[Coin::new(800, denom)]); - let msg = ExecuteMsg::RedeemAndTransfer { recipient: None }; - let res_redeem = execute(deps.as_mut(), mock_env(ADAPTER_CONTRACT), info_redeem, msg); - - assert!(res_redeem.is_ok()); -} diff --git a/packages/testenv/Cargo.toml b/packages/testenv/Cargo.toml new file mode 100644 index 0000000..236eb8b --- /dev/null +++ b/packages/testenv/Cargo.toml @@ -0,0 +1,26 @@ +[package] +description = "Common testing helpers for Injective Test Tube" +edition = "2021" +license = "Apache-2.0" +name = "testenv" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] + +[dependencies] +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +enumset = { workspace = true } +injective-cosmwasm = { workspace = true } +injective-math = { workspace = true } +injective-std = { workspace = true } +injective-test-tube = { workspace = true } +injective-testing = { workspace = true } +prost = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +serde-cw-value = { workspace = true } +serde-json-wasm = { workspace = true } +thiserror = { workspace = true } diff --git a/packages/testenv/src/lib.rs b/packages/testenv/src/lib.rs new file mode 100644 index 0000000..b5614dd --- /dev/null +++ b/packages/testenv/src/lib.rs @@ -0,0 +1 @@ +pub mod utils; diff --git a/packages/testenv/src/utils.rs b/packages/testenv/src/utils.rs new file mode 100644 index 0000000..c0c097e --- /dev/null +++ b/packages/testenv/src/utils.rs @@ -0,0 +1,76 @@ +use cosmwasm_std::{Addr, Uint128}; +use injective_cosmwasm::{checked_address_to_subaccount_id, SubaccountId}; +use injective_std::types::cosmos::bank::v1beta1::QueryBalanceRequest; +use injective_test_tube::{Account, Bank, InjectiveTestApp, Module, SigningAccount}; +use injective_testing::{ + mocks::{MOCK_ATOM_DECIMALS, MOCK_ATOM_DENOM, MOCK_BASE_DECIMALS, MOCK_BASE_DENOM, MOCK_QUOTE_DECIMALS, MOCK_QUOTE_DENOM}, + utils::str_coin, +}; +use std::{collections::HashMap, str::FromStr}; + +pub const MOCK_MARKET_ID: &str = "0x427aee334987c52fa7b567b2662bdbb68614e48c000000000000000000000000"; +pub const MOCK_TIA_DENOM: &str = "tia"; + +pub struct TraderInfo { + pub account: SigningAccount, + pub subaccount_id: SubaccountId, +} + +pub struct Setup { + pub app: InjectiveTestApp, + pub owner: SigningAccount, + pub traders: Vec, + pub denoms: HashMap, +} + +impl Setup { + pub fn new() -> Self { + let app = InjectiveTestApp::new(); + + let mut denoms = HashMap::new(); + denoms.insert("atom".to_string(), MOCK_ATOM_DENOM.to_string()); + denoms.insert("quote".to_string(), MOCK_QUOTE_DENOM.to_string()); + denoms.insert("base".to_string(), MOCK_BASE_DENOM.to_string()); + denoms.insert("tia".to_string(), MOCK_TIA_DENOM.to_string()); + + let owner = app + .init_account(&[ + str_coin("1000000", MOCK_ATOM_DENOM, MOCK_ATOM_DECIMALS), + str_coin("1000000", MOCK_BASE_DENOM, MOCK_BASE_DECIMALS), + str_coin("1000000", MOCK_QUOTE_DENOM, MOCK_QUOTE_DECIMALS), + str_coin("1000000", MOCK_TIA_DENOM, MOCK_QUOTE_DECIMALS), + ]) + .unwrap(); + + let mut traders: Vec = Vec::new(); + for _ in 0..10 { + let trader = app.init_account(&[str_coin("1000000", MOCK_BASE_DENOM, MOCK_BASE_DECIMALS)]).unwrap(); + + let trader_subaccount_id = checked_address_to_subaccount_id(&Addr::unchecked(trader.address()), 1u32); + + traders.push(TraderInfo { + account: trader, + subaccount_id: trader_subaccount_id, + }); + } + + Self { app, owner, traders, denoms } + } + + pub fn get_balance(&self, address: String, denom: String) -> Uint128 { + let bank = Bank::new(&self.app); + + let response = bank.query_balance(&QueryBalanceRequest { address, denom }).unwrap(); + + match response.balance { + Some(balance) => Uint128::from_str(&balance.amount).unwrap(), + None => Uint128::zero(), + } + } +} + +impl Default for Setup { + fn default() -> Self { + Self::new() + } +} From 1f3766f5e9b92e585b45020d803679485fa231b8 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 24 Sep 2024 14:38:15 +0100 Subject: [PATCH 2/7] feat: update config.toml --- .cargo/config.toml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8d4bc73 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --example schema" From 737254670b07c43fd1ea7708705844ce1d3d4eb4 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 24 Sep 2024 17:08:15 +0100 Subject: [PATCH 3/7] feat: fix ci --- .cargo/config | 6 ------ .github/workflows/rust.yaml | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index 8d4bc73..0000000 --- a/.cargo/config +++ /dev/null @@ -1,6 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib" -integration-test = "test --test integration" -schema = "run --example schema" diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 406f16c..a671215 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -32,6 +32,14 @@ jobs: profile: minimal toolchain: stable override: true + + - name: Compile WASM contracts + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --lib --target wasm32-unknown-unknown --locked --workspace --exclude testenv + env: + RUSTFLAGS: "-C link-arg=-s" - name: run tests uses: actions-rs/cargo@v1 with: From 7aefb9aeaccfc6858f7f7e42bfa691cdf8130c85 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 24 Sep 2024 17:14:08 +0100 Subject: [PATCH 4/7] chore: update CI --- .github/workflows/integration_tests.yaml | 39 ++++++++++++++ .github/workflows/rust.yaml | 67 ------------------------ .github/workflows/unit_tests.yml | 60 +++++++++++++++++++++ 3 files changed, 99 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/integration_tests.yaml delete mode 100644 .github/workflows/rust.yaml create mode 100644 .github/workflows/unit_tests.yml diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml new file mode 100644 index 0000000..28738b7 --- /dev/null +++ b/.github/workflows/integration_tests.yaml @@ -0,0 +1,39 @@ +# Based on https://github.com/actions-rs/example/blob/master/.github/workflows/quickstart.yml + +on: + push: + pull_request: + types: [opened] + +name: Test tube integration tests + +jobs: + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: 1.78.0 + target: wasm32-unknown-unknown + override: true + components: llvm-tools-preview + + - name: Compile WASM contracts + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --lib --target wasm32-unknown-unknown --locked --workspace --exclude testenv + env: + RUSTFLAGS: "-C link-arg=-s" + + - name: Run Integration Tests + uses: actions-rs/cargo@v1 + with: + command: test + args: --features integration diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml deleted file mode 100644 index a671215..0000000 --- a/.github/workflows/rust.yaml +++ /dev/null @@ -1,67 +0,0 @@ -on: push -name: Rust CI -jobs: - check: - name: check - runs-on: ubuntu-latest - steps: - - name: checkout sources - uses: actions/checkout@v2 - - name: install stable toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - name: check for errors - uses: actions-rs/cargo@v1 - with: - command: check - args: --locked - env: - RUST_BACKTRACE: 1 - test: - name: test - runs-on: ubuntu-latest - steps: - - name: checkout sources - uses: actions/checkout@v2 - - name: install stable toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - name: Compile WASM contracts - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --lib --target wasm32-unknown-unknown --locked --workspace --exclude testenv - env: - RUSTFLAGS: "-C link-arg=-s" - - name: run tests - uses: actions-rs/cargo@v1 - with: - command: unit-test - args: --locked --tests - env: - RUST_BACKTRACE: 1 - clippy: - name: clippy - runs-on: ubuntu-latest - steps: - - name: checkout sources - uses: actions/checkout@v2 - - name: install stable toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - components: clippy - override: true - - name: run linter - uses: actions-rs/cargo@v1 - with: - command: clippy - args: -- -D warnings diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..35eddab --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,60 @@ +# Based on https://github.com/actions-rs/example/blob/master/.github/workflows/quickstart.yml + +on: + push: + pull_request: + types: [opened] + +name: Unit tests + lints + +jobs: + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: 1.78.0 + target: wasm32-unknown-unknown + override: true + components: llvm-tools-preview + + - name: Run Integration Tests + uses: actions-rs/cargo@v1 + with: + command: test + + lints: + name: Lints + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: 1.78.0 + override: true + components: rustfmt, clippy + + - name: Run cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + - name: Show Clippy version + run: cargo clippy --version + + - name: Run cargo clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --tests -- -D warnings From 40ee93cbb50dd8f35ee5d29f54c898d1e6e8ea18 Mon Sep 17 00:00:00 2001 From: maxrobot Date: Tue, 24 Sep 2024 18:03:10 +0100 Subject: [PATCH 5/7] fix: ci --- .github/workflows/integration_tests.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index 28738b7..72c39b2 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -36,4 +36,3 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --features integration From c0bf3dfd8cddec1687f8f20628f4ed17e649280e Mon Sep 17 00:00:00 2001 From: jose Date: Mon, 7 Oct 2024 09:25:33 +0200 Subject: [PATCH 6/7] fix: cargo file --- Cargo.lock | 5 ----- Cargo.toml | 5 +---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ab439f..7b62bc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3614,8 +3614,3 @@ dependencies = [ "quote", "syn 2.0.77", ] - -[[patch.unused]] -name = "injective-cosmwasm" -version = "0.1.74" -source = "git+https://github.com/InjectiveLabs/cw-injective.git?branch=dev#f0c00001f04ee004f9c97ecbe012127c7111bc44" diff --git a/Cargo.toml b/Cargo.toml index 1f67ffb..409f89a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,4 @@ opt-level = 3 overflow-checks = true rpath = false -[patch.crates-io] -#injective-cosmwasm = { path = "../cw-injective/packages/injective-cosmwasm"} -injective-cosmwasm = { git = "https://github.com/InjectiveLabs/cw-injective.git", branch = "dev" } -#cw20-base = { path = "../cw-plus-inj/contracts/cw20-base" } + From 65872d2840e3eb8823d2c503372eefee11921d97 Mon Sep 17 00:00:00 2001 From: jose Date: Mon, 7 Oct 2024 10:16:31 +0200 Subject: [PATCH 7/7] fix: github actions --- .github/workflows/unit_tests.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 35eddab..2d5affb 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -24,6 +24,14 @@ jobs: override: true components: llvm-tools-preview + - name: Compile WASM contracts + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --lib --target wasm32-unknown-unknown --locked --workspace --exclude testenv + env: + RUSTFLAGS: "-C link-arg=-s" + - name: Run Integration Tests uses: actions-rs/cargo@v1 with: