diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index fef40b92..ebacfedc 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -48,6 +48,8 @@ jobs: - TestWithContractTestSuite/TestSendWasmMsgsProtobufEncoding - TestWithContractTestSuite/TestMigrateOrderedToUnordered - TestWithContractTestSuite/TestCloseChannel_Protobuf_Unordered + - TestWithContractTestSuite/TestBankAndStargateQueries + - TestWithContractTestSuite/TestStakingQueries name: ${{ matrix.test }} runs-on: ubuntu-latest steps: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8da6f69d..5d8587fc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -21,7 +21,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.73.0 + toolchain: 1.78.0 target: wasm32-unknown-unknown override: true @@ -52,7 +52,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.73.0 + toolchain: 1.78.0 override: true - name: Run unit tests @@ -80,7 +80,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.73.0 + toolchain: 1.78.0 override: true - name: Run unit tests @@ -108,7 +108,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.73.0 + toolchain: 1.78.0 override: true - name: Run unit tests @@ -125,6 +125,34 @@ jobs: command: build args: --locked --features=staking + build-with-query: + name: Build with Query Feature + 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: 1.78.0 + override: true + + - name: Run unit tests + uses: actions-rs/cargo@v1 + with: + command: unit-test + args: --locked --features=staking + env: + RUST_BACKTRACE: 1 + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: --locked --features=query + lints: name: Lint Contract runs-on: ubuntu-latest @@ -136,7 +164,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: 1.73.0 + toolchain: 1.78.0 override: true components: rustfmt, clippy diff --git a/CHANGELOG.md b/CHANGELOG.md index 531f17c3..ca85931d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,24 @@ ## [Unreleased] -### API Breaking Changes +### Features -- Improved the query helpers. (https://github.com/srdtrk/cw-ica-controller/pull/114) -- Changed `call` to `execute` in `helpers.rs`. (https://github.com/srdtrk/cw-ica-controller/pull/114) +- Added support for ICA queries. (https://github.com/srdtrk/cw-ica-controller/issues/88) ### API Breaking Changes +- Added a `query_result` field to `IcaControllerCallbackMsg`. (https://github.com/srdtrk/cw-ica-controller/pull/118) +- Added a `queries` field to `ExecuteMsg::SendCosmosMsgs`. (https://github.com/srdtrk/cw-ica-controller/pull/118) +- Improved the query helpers. (https://github.com/srdtrk/cw-ica-controller/pull/114) +- Changed `call` to `execute` in `helpers.rs`. (https://github.com/srdtrk/cw-ica-controller/pull/114) - Removed support for `proto3json` encoding. (https://github.com/srdtrk/cw-ica-controller/pull/92) - Removed `tx_encoding` field from `ChannelOpenInitOptions`. (https://github.com/srdtrk/cw-ica-controller/pull/92) - Removed `ExecuteMsg::SendCustomIcaMessages`. (https://github.com/srdtrk/cw-ica-controller/pull/92) +### State Breaking Changes + +- Removed support for CosmWasm (and wasmvm) version `v1.3`. (https://github.com/srdtrk/cw-ica-controller/pull/90) + ## v0.5.0 (2024-02-05) ### Features diff --git a/Cargo.lock b/Cargo.lock index c39286ec..b650eec8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anybuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5f1dee23caf80904249463cc4493b6789c2250f88c8f8d9160de5c6099bfe7" + [[package]] name = "anyhow" version = "1.0.86" @@ -43,6 +64,12 @@ 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.6.0" @@ -79,6 +106,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -94,18 +127,43 @@ dependencies = [ "serde", ] +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + [[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 = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cosmos-sdk-proto" version = "0.20.0" @@ -114,7 +172,18 @@ checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ "prost", "prost-types", - "tendermint-proto", + "tendermint-proto 0.34.1", +] + +[[package]] +name = "cosmos-sdk-proto" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e23f6ab56d5f031cde05b8b82a5fefd3a1a223595c79e32317a97189e612bc" +dependencies = [ + "prost", + "prost-types", + "tendermint-proto 0.35.0", ] [[package]] @@ -245,7 +314,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcd5af76ac0cb5ea40a715191028cbddeb0f682c9771f7d1c57ea24f42dec704" dependencies = [ - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus", @@ -263,7 +332,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83994aa638a9943eb0eca4fd82a21d9261c61763b609f2685a5fb01dff24aaa4" dependencies = [ - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus", @@ -281,7 +350,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62b41020a146c640e6411ca43f43bc5857b8a8ba818099c40ae090cfae71c49" dependencies = [ - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "cosmwasm-schema", "cosmwasm-std", "cw-ownable", @@ -300,7 +369,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebb040438ea955087568b4269090a2c282cd3b433de7f8dc5d80cdbfbbe1a5ba" dependencies = [ - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "cosmwasm-schema", "cosmwasm-std", "cw-ica-controller-derive", @@ -320,7 +389,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff14c2d8a7f11dbbbf5e6e758aa8634679dbe87ab7aac6ce2b8cc2b3eff4731a" dependencies = [ - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "cosmwasm-schema", "cosmwasm-std", "cw-ica-controller-derive", @@ -338,8 +407,9 @@ dependencies = [ name = "cw-ica-controller" version = "0.6.0" dependencies = [ + "anybuf", "base64 0.13.1", - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.21.1", "cosmwasm-schema", "cosmwasm-std", "cw-ica-controller 0.1.3", @@ -351,10 +421,12 @@ dependencies = [ "cw-ownable", "cw-storage-plus", "cw2", + "prost", "schemars", "semver", "serde", "serde-json-wasm 1.0.1", + "serde_with", "thiserror", ] @@ -436,6 +508,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.66", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.66", +] + [[package]] name = "der" version = "0.7.9" @@ -453,6 +560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -514,7 +622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek", - "hashbrown", + "hashbrown 0.12.3", "hex", "rand_core 0.6.4", "serde", @@ -547,6 +655,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ff" version = "0.13.0" @@ -566,6 +680,12 @@ dependencies = [ "paste", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "forward_ref" version = "1.0.0" @@ -614,6 +734,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hex" version = "0.4.3" @@ -629,6 +755,57 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + [[package]] name = "itertools" version = "0.12.1" @@ -644,6 +821,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "k256" version = "0.13.1" @@ -664,6 +850,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "num-conv" version = "0.1.0" @@ -681,6 +873,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -918,6 +1121,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sha2" version = "0.9.9" @@ -968,6 +1201,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.5.0" @@ -1013,7 +1252,25 @@ checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" dependencies = [ "bytes", "flex-error", - "num-derive", + "num-derive 0.3.3", + "num-traits", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" +dependencies = [ + "bytes", + "flex-error", + "num-derive 0.4.2", "num-traits", "prost", "prost-types", @@ -1050,8 +1307,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", + "serde", "time-core", "time-macros", ] @@ -1096,6 +1355,133 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zeroize" version = "1.8.1" diff --git a/Cargo.toml b/Cargo.toml index 3472474b..0c564435 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,9 +27,10 @@ overflow-checks = true [features] # disable export feature to disable all instantiate/execute/query exports -default = ["export", "staking"] -export = [] +default = ["export", "staking", "query"] +export = ["query", "staking"] staking = ["cosmwasm-std/staking"] +query = ["dep:prost"] [package.metadata.scripts] optimize = """docker run --rm -v "$(pwd)":/code \ @@ -51,10 +52,13 @@ schemars = "0.8.10" serde = { version = "1.0", default-features = false, features = ["derive"] } serde-json-wasm = "1.0.0" thiserror = "1.0.50" -cosmos-sdk-proto = { version = "0.20.0", default-features = false, features = ["cosmwasm"] } +cosmos-sdk-proto = { version = "0.21.1", default-features = false, features = ["cosmwasm"] } semver = "1.0" cw-ownable = "0.5.1" cw-ica-controller-derive = "0.4.2" +prost = { version = "0.12", optional = true } +anybuf = "0.5.0" +serde_with = "3.8.1" [dev-dependencies] base64 = "0.13.1" diff --git a/e2e/Readme.md b/e2e/Readme.md index ca7c33aa..e1ddf8b6 100644 --- a/e2e/Readme.md +++ b/e2e/Readme.md @@ -29,6 +29,8 @@ All contract tests are located in `interchaintest/contract_test.go` file. Curren - TestWithContractTestSuite/TestSendWasmMsgsProtobufEncoding - TestWithContractTestSuite/TestMigrateOrderedToUnordered - TestWithContractTestSuite/TestCloseChannel_Protobuf_Unordered +- TestWithContractTestSuite/TestBankAndStargateQueries +- TestWithContractTestSuite/TestStakingQueries To run the tests locally, run the following command in the root of the repository: diff --git a/e2e/interchaintestv8/chainconfig/chain_config.go b/e2e/interchaintestv8/chainconfig/chain_config.go index ee058d84..1e2c8703 100644 --- a/e2e/interchaintestv8/chainconfig/chain_config.go +++ b/e2e/interchaintestv8/chainconfig/chain_config.go @@ -30,7 +30,7 @@ var DefaultChainSpecs = []*interchaintest.ChainSpec{ NoHostMount: false, }, }, - // -- WASMD -- + // -- IBC-Go -- { ChainConfig: ibc.ChainConfig{ Type: "cosmos", diff --git a/e2e/interchaintestv8/contract_test.go b/e2e/interchaintestv8/contract_test.go index 103e3f0e..2496829e 100644 --- a/e2e/interchaintestv8/contract_test.go +++ b/e2e/interchaintestv8/contract_test.go @@ -797,7 +797,7 @@ func (s *ContractTestSuite) TestIcaContractTimeoutPacket_Ordered_Protobuf() { // Check if contract channel state was updated: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateClosed, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateClosed, contractChannelState.ChannelStatus) })) s.Require().True(s.Run("TestChannelReopening", func() { @@ -833,7 +833,7 @@ func (s *ContractTestSuite) TestIcaContractTimeoutPacket_Ordered_Protobuf() { // Check if contract channel state was updated: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateOpen, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateOpen, contractChannelState.ChannelStatus) s.Require().Equal(wasmdChannel.ConnectionHops[0], contractChannelState.Channel.ConnectionId) s.Require().Equal(wasmdChannel.ChannelID, contractChannelState.Channel.Endpoint.ChannelId) s.Require().Equal(wasmdChannel.PortID, contractChannelState.Channel.Endpoint.PortId) @@ -960,7 +960,7 @@ func (s *ContractTestSuite) TestIcaContractTimeoutPacket_Unordered_Protobuf() { // Check if contract channel state is still open: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateOpen, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateOpen, contractChannelState.ChannelStatus) })) s.Require().True(s.Run("TestSendCustomIcaMessagesAfterTimeout", func() { @@ -1041,7 +1041,7 @@ func (s *ContractTestSuite) TestMigrateOrderedToUnordered() { // Check if contract channel state was updated: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateClosed, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateClosed, contractChannelState.ChannelStatus) })) s.Require().True(s.Run("TestChannelReopening", func() { @@ -1086,7 +1086,7 @@ func (s *ContractTestSuite) TestMigrateOrderedToUnordered() { // Check if contract channel state was updated: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateOpen, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateOpen, contractChannelState.ChannelStatus) s.Require().Equal(wasmdChannel.ConnectionHops[0], contractChannelState.Channel.ConnectionId) s.Require().Equal(wasmdChannel.ChannelID, contractChannelState.Channel.Endpoint.ChannelId) s.Require().Equal(wasmdChannel.PortID, contractChannelState.Channel.Endpoint.PortId) @@ -1183,7 +1183,7 @@ func (s *ContractTestSuite) TestCloseChannel_Protobuf_Unordered() { // Check if contract channel state was updated: contractChannelState, err := s.Contract.QueryClient().GetChannel(ctx, &cwicacontroller.QueryMsg_GetChannel{}) s.Require().NoError(err) - s.Require().Equal(cwicacontroller.Status_StateClosed, contractChannelState.ChannelStatus) + s.Require().Equal(cwicacontroller.ChannelStatus_StateClosed, contractChannelState.ChannelStatus) })) } diff --git a/e2e/interchaintestv8/e2esuite/suite.go b/e2e/interchaintestv8/e2esuite/suite.go index d6d77290..86651382 100644 --- a/e2e/interchaintestv8/e2esuite/suite.go +++ b/e2e/interchaintestv8/e2esuite/suite.go @@ -10,6 +10,8 @@ import ( sdkmath "cosmossdk.io/math" + ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported" + interchaintest "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/ibc" @@ -18,6 +20,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/testutil" "github.com/srdtrk/go-codegen/e2esuite/v8/chainconfig" + "github.com/srdtrk/go-codegen/e2esuite/v8/testvalues" ) // TestSuite is a suite of tests that require two chains and a relayer @@ -92,7 +95,7 @@ func (s *TestSuite) SetupSuite(ctx context.Context) { s.Require().NoError(populateQueryReqToPath(ctx, s.ChainB)) // Fund a user accounts - userFunds := sdkmath.NewInt(10_000_000_000) + userFunds := sdkmath.NewInt(testvalues.StartingTokenAmount) users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, s.ChainA, s.ChainB) s.UserA = users[0] s.UserB = users[1] @@ -121,7 +124,7 @@ func (s *TestSuite) SetupSuite(ctx context.Context) { // localhost is always a connection since ibc-go v7.1+ s.Require().Equal(2, len(connections)) wasmdConnection := connections[0] - s.Require().NotEqual("connection-localhost", wasmdConnection.ID) + s.Require().NotEqual(ibcexported.LocalhostConnectionID, wasmdConnection.ID) // Query for the newly created connection in simd connections, err = s.Relayer.GetConnections(ctx, s.ExecRep, s.ChainB.Config().ChainID) @@ -129,7 +132,7 @@ func (s *TestSuite) SetupSuite(ctx context.Context) { // localhost is always a connection since ibc-go v7.1+ s.Require().Equal(2, len(connections)) simdConnection := connections[0] - s.Require().NotEqual("connection-localhost", simdConnection.ID) + s.Require().NotEqual(ibcexported.LocalhostConnectionID, simdConnection.ID) // Start the relayer and set the cleanup function. err = s.Relayer.StartRelayer(ctx, s.ExecRep, s.PathName) diff --git a/e2e/interchaintestv8/e2esuite/utils.go b/e2e/interchaintestv8/e2esuite/utils.go index 6959eb48..d74fca29 100644 --- a/e2e/interchaintestv8/e2esuite/utils.go +++ b/e2e/interchaintestv8/e2esuite/utils.go @@ -13,16 +13,18 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/ibc" "github.com/strangelove-ventures/interchaintest/v8/testutil" + + "github.com/srdtrk/go-codegen/e2esuite/v8/testvalues" ) // FundAddressChainA sends funds to the given address on Chain A. -// The amount sent is 1,000,000,000 of the chain's denom. +// The amount sent is testvalues.FundingAmount of the chain's denom. func (s *TestSuite) FundAddressChainA(ctx context.Context, address string) { s.fundAddress(ctx, s.ChainA, s.UserA.KeyName(), address) } // FundAddressChainB sends funds to the given address on Chain B. -// The amount sent is 1,000,000,000 of the chain's denom. +// The amount sent is testvalues.FundingAmount of the chain's denom. func (s *TestSuite) FundAddressChainB(ctx context.Context, address string) { s.fundAddress(ctx, s.ChainB, s.UserB.KeyName(), address) } @@ -85,7 +87,7 @@ func (s *TestSuite) fundAddress(ctx context.Context, chain *cosmos.CosmosChain, err := chain.SendFunds(ctx, keyName, ibc.WalletAmount{ Address: address, Denom: chain.Config().Denom, - Amount: math.NewInt(1_000_000_000), + Amount: math.NewInt(testvalues.FundingAmount), }) s.Require().NoError(err) diff --git a/e2e/interchaintestv8/icaicq_test.go b/e2e/interchaintestv8/icaicq_test.go new file mode 100644 index 00000000..67e3d43e --- /dev/null +++ b/e2e/interchaintestv8/icaicq_test.go @@ -0,0 +1,343 @@ +package main + +import ( + "context" + + "github.com/cosmos/gogoproto/proto" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types" + + "github.com/strangelove-ventures/interchaintest/v8/testutil" + + "github.com/srdtrk/go-codegen/e2esuite/v8/e2esuite" + "github.com/srdtrk/go-codegen/e2esuite/v8/types/callbackcounter" + "github.com/srdtrk/go-codegen/e2esuite/v8/types/cwicacontroller" +) + +// `TestBankQueries` tests all allowed bank queries in the SendCosmosMsgs message. The following queries are tested: +// - Bank::Balance +// - Bank::AllBalances +// - Bank::AllDenomMetadata +// - Bank::Supply +// TODO: Bank::DenomMetadata +func (s *ContractTestSuite) TestBankAndStargateQueries() { + ctx := context.Background() + + // This starts the chains, relayer, creates the user accounts, creates the ibc clients and connections, + // sets up the contract and does the channel handshake for the contract test suite. + s.SetupContractTestSuite(ctx, cwicacontroller.IbcOrder_OrderUnordered) + wasmd, simd := s.ChainA, s.ChainB + wasmdUser, simdUser := s.UserA, s.UserB + + // Fund the ICA address: + s.FundAddressChainB(ctx, s.IcaContractToAddrMap[s.Contract.Address]) + + s.Require().True(s.Run("BankQuery_Balance", func() { + balanceQueryMsg := cwicacontroller.ExecuteMsg{ + SendCosmosMsgs: &cwicacontroller.ExecuteMsg_SendCosmosMsgs{ + Messages: []cwicacontroller.CosmosMsg_for_Empty{}, + Queries: []cwicacontroller.QueryRequest_for_Empty{ + { + Bank: &cwicacontroller.QueryRequest_for_Empty_Bank{ + Balance: &cwicacontroller.BankQuery_Balance{ + Address: simdUser.FormattedAddress(), + Denom: simd.Config().Denom, + }, + }, + }, + }, + }, + } + + expBalance, err := simd.GetBalance(ctx, simdUser.FormattedAddress(), simd.Config().Denom) + s.Require().NoError(err) + + _, err = s.Contract.Execute(ctx, wasmdUser.KeyName(), balanceQueryMsg) + s.Require().NoError(err) + + err = testutil.WaitForBlocks(ctx, 5, wasmd, simd) + s.Require().NoError(err) + + // Check if contract callbacks were executed: + callbackCounter, err := s.CallbackCounterContract.QueryClient().GetCallbackCounter(ctx, &callbackcounter.QueryMsg_GetCallbackCounter{}) + s.Require().NoError(err) + s.Require().Equal(int(1), len(callbackCounter.Success)) + s.Require().Equal(int(0), len(callbackCounter.Error)) + s.Require().Equal(int(0), len(callbackCounter.Timeout)) + + s.Require().True(s.Run("test unmarshaling ica acknowledgement", func() { + icaAck := &sdk.TxMsgData{} + s.Require().True(s.Run("unmarshal ica response", func() { + err := proto.Unmarshal(callbackCounter.Success[0].OnAcknowledgementPacketCallback.IcaAcknowledgement.Result.Unwrap(), icaAck) + s.Require().NoError(err) + s.Require().Len(icaAck.GetMsgResponses(), 1) + })) + + queryTxResp := &icahosttypes.MsgModuleQuerySafeResponse{} + s.Require().True(s.Run("unmarshal MsgModuleQuerySafeResponse", func() { + err := proto.Unmarshal(icaAck.MsgResponses[0].Value, queryTxResp) + s.Require().NoError(err) + s.Require().Len(queryTxResp.Responses, 1) + })) + + balanceResp := &banktypes.QueryBalanceResponse{} + s.Require().True(s.Run("unmarshal and verify bank query response", func() { + err := proto.Unmarshal(queryTxResp.Responses[0], balanceResp) + s.Require().NoError(err) + s.Require().Equal(simd.Config().Denom, balanceResp.Balance.Denom) + s.Require().Equal(expBalance.Int64(), balanceResp.Balance.Amount.Int64()) + })) + })) + + s.Require().True(s.Run("verify query result", func() { + s.Require().Nil(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Error) + s.Require().NotNil(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success) + s.Require().Len(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses, 1) + s.Require().Equal(simd.Config().Denom, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Bank.Balance.Amount.Denom) + s.Require().Equal(expBalance.String(), string(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Bank.Balance.Amount.Amount)) + })) + })) + + s.Require().True(s.Run("Other bank queries and stargate query", func() { + allBankQueriesMsg := cwicacontroller.ExecuteMsg{ + SendCosmosMsgs: &cwicacontroller.ExecuteMsg_SendCosmosMsgs{ + Messages: []cwicacontroller.CosmosMsg_for_Empty{}, + Queries: []cwicacontroller.QueryRequest_for_Empty{ + { + Bank: &cwicacontroller.QueryRequest_for_Empty_Bank{ + AllBalances: &cwicacontroller.BankQuery_AllBalances{ + Address: simdUser.FormattedAddress(), + }, + }, + }, + // fail: need to set metadata first + // { + // Bank: &cwicacontroller.QueryRequest_for_Empty_Bank{ + // DenomMetadata: &cwicacontroller.BankQuery_DenomMetadata{ + // Denom: simd.Config().Denom, + // }, + // }, + // }, + { + Bank: &cwicacontroller.QueryRequest_for_Empty_Bank{ + AllDenomMetadata: &cwicacontroller.BankQuery_AllDenomMetadata{}, + }, + }, + { + Bank: &cwicacontroller.QueryRequest_for_Empty_Bank{ + Supply: &cwicacontroller.BankQuery_Supply{ + Denom: simd.Config().Denom, + }, + }, + }, + { + Stargate: cwicacontroller.NewStargateQuery_FromProto("/cosmos.auth.v1beta1.Query/ModuleAccountByName", &authtypes.QueryModuleAccountByNameRequest{ + Name: govtypes.ModuleName, + }), + }, + }, + }, + } + + expBalance, err := simd.GetBalance(ctx, simdUser.FormattedAddress(), simd.Config().Denom) + s.Require().NoError(err) + expSupply, err := e2esuite.GRPCQuery[banktypes.QueryTotalSupplyResponse](ctx, simd, &banktypes.QueryTotalSupplyRequest{}) + s.Require().NoError(err) + + expStargateResp, err := e2esuite.GRPCQuery[authtypes.QueryModuleAccountByNameResponse](ctx, simd, &authtypes.QueryModuleAccountByNameRequest{ + Name: govtypes.ModuleName, + }) + s.Require().NoError(err) + + _, err = s.Contract.Execute(ctx, wasmdUser.KeyName(), allBankQueriesMsg) + s.Require().NoError(err) + + err = testutil.WaitForBlocks(ctx, 5, wasmd, simd) + s.Require().NoError(err) + + // Check if contract callbacks were executed: + callbackCounter, err := s.CallbackCounterContract.QueryClient().GetCallbackCounter(ctx, &callbackcounter.QueryMsg_GetCallbackCounter{}) + s.Require().NoError(err) + s.Require().Equal(int(2), len(callbackCounter.Success)) + s.Require().Equal(int(0), len(callbackCounter.Error)) + s.Require().Equal(int(0), len(callbackCounter.Timeout)) + + s.Require().True(s.Run("verify query result", func() { + s.Require().Nil(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Error) + s.Require().NotNil(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success) + s.Require().Len(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses, 4) + + s.Require().Len(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Bank.AllBalances.Amount, 1) + s.Require().Equal(simd.Config().Denom, callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Bank.AllBalances.Amount[0].Denom) + s.Require().Equal(expBalance.String(), string(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Bank.AllBalances.Amount[0].Amount)) + + s.Require().Len(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Bank.AllDenomMetadata.Metadata, 0) + + s.Require().Equal(simd.Config().Denom, callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[2].Bank.Supply.Amount.Denom) + s.Require().Less(expSupply.Supply[0].Amount.String(), string(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[2].Bank.Supply.Amount.Amount)) + + s.Require().Equal("/cosmos.auth.v1beta1.Query/ModuleAccountByName", callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[3].Stargate.Path) + + resp := &authtypes.QueryModuleAccountByNameResponse{} + err = proto.Unmarshal(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[3].Stargate.Data.Unwrap(), resp) + s.Require().NoError(err) + + s.Require().Equal(expStargateResp, resp) + })) + })) +} + +// `TestStakingQuery` tests all allowed staking queries in the SendCosmosMsgs message. The following queries are tested: +// - Staking::Delegation +// - Staking::AllDelegations +// - Staking::Validator +// - Staking::AllValidator +// - Staking::BondedDenom +func (s *ContractTestSuite) TestStakingQueries() { + ctx := context.Background() + + // This starts the chains, relayer, creates the user accounts, creates the ibc clients and connections, + // sets up the contract and does the channel handshake for the contract test suite. + s.SetupContractTestSuite(ctx, cwicacontroller.IbcOrder_OrderUnordered) + wasmd, simd := s.ChainA, s.ChainB + wasmdUser, _ := s.UserA, s.UserB + + // Fund the ICA address: + icaAddress := s.IcaContractToAddrMap[s.Contract.Address] + s.FundAddressChainB(ctx, icaAddress) + + var validator string + s.Require().True(s.Run("Query after msg", func() { + var err error + validator, err = simd.Validators[0].KeyBech32(ctx, "validator", "val") + s.Require().NoError(err) + + // Stake some tokens through CosmosMsgs: + stakeAmount := cwicacontroller.Coin{ + Denom: simd.Config().Denom, + Amount: "10000000", + } + stakeCosmosMsg := cwicacontroller.CosmosMsg_for_Empty{ + Staking: &cwicacontroller.CosmosMsg_for_Empty_Staking{ + Delegate: &cwicacontroller.StakingMsg_Delegate{ + Validator: validator, + Amount: stakeAmount, + }, + }, + } + // Execute the contract: + execMsgWithQueries := cwicacontroller.ExecuteMsg{ + SendCosmosMsgs: &cwicacontroller.ExecuteMsg_SendCosmosMsgs{ + Messages: []cwicacontroller.CosmosMsg_for_Empty{stakeCosmosMsg}, + Queries: []cwicacontroller.QueryRequest_for_Empty{ + { + Staking: &cwicacontroller.QueryRequest_for_Empty_Staking{ + Delegation: &cwicacontroller.StakingQuery_Delegation{ + Validator: validator, + Delegator: icaAddress, + }, + }, + }, + { + Staking: &cwicacontroller.QueryRequest_for_Empty_Staking{ + AllDelegations: &cwicacontroller.StakingQuery_AllDelegations{ + Delegator: icaAddress, + }, + }, + }, + }, + }, + } + _, err = s.Contract.Execute(ctx, wasmdUser.KeyName(), execMsgWithQueries) + s.Require().NoError(err) + + err = testutil.WaitForBlocks(ctx, 5, wasmd, simd) + s.Require().NoError(err) + + callbackCounter, err := s.CallbackCounterContract.QueryClient().GetCallbackCounter(ctx, &callbackcounter.QueryMsg_GetCallbackCounter{}) + s.Require().NoError(err) + s.Require().Equal(int(1), len(callbackCounter.Success)) + s.Require().Equal(int(0), len(callbackCounter.Error)) + s.Require().Equal(int(0), len(callbackCounter.Timeout)) + + s.Require().True(s.Run("verify query result", func() { + s.Require().Nil(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Error) + s.Require().NotNil(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success) + s.Require().Len(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses, 2) + + s.Require().Equal(validator, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Delegation.Delegation.Validator) + s.Require().Equal(icaAddress, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Delegation.Delegation.Delegator) + s.Require().Equal(stakeAmount.Denom, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Delegation.Delegation.Amount.Denom) + s.Require().Equal(string(stakeAmount.Amount), string(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Delegation.Delegation.Amount.Amount)) + + s.Require().Len(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllDelegations.Delegations, 1) + s.Require().Equal(validator, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllDelegations.Delegations[0].Validator) + s.Require().Equal(icaAddress, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllDelegations.Delegations[0].Delegator) + s.Require().Equal(stakeAmount.Denom, callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllDelegations.Delegations[0].Amount.Denom) + s.Require().Equal(string(stakeAmount.Amount), string(callbackCounter.Success[0].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllDelegations.Delegations[0].Amount.Amount)) + })) + })) + + s.Require().True(s.Run("Other staking queries", func() { + execMsgWithQueries := cwicacontroller.ExecuteMsg{ + SendCosmosMsgs: &cwicacontroller.ExecuteMsg_SendCosmosMsgs{ + Queries: []cwicacontroller.QueryRequest_for_Empty{ + { + Staking: &cwicacontroller.QueryRequest_for_Empty_Staking{ + Validator: &cwicacontroller.StakingQuery_Validator{ + Address: validator, + }, + }, + }, + { + Staking: &cwicacontroller.QueryRequest_for_Empty_Staking{ + AllValidators: &cwicacontroller.StakingQuery_AllValidators{}, + }, + }, + { + Staking: &cwicacontroller.QueryRequest_for_Empty_Staking{ + BondedDenom: &cwicacontroller.StakingQuery_BondedDenom{}, + }, + }, + }, + }, + } + + _, err := s.Contract.Execute(ctx, wasmdUser.KeyName(), execMsgWithQueries) + s.Require().NoError(err) + + err = testutil.WaitForBlocks(ctx, 5, wasmd, simd) + s.Require().NoError(err) + + callbackCounter, err := s.CallbackCounterContract.QueryClient().GetCallbackCounter(ctx, &callbackcounter.QueryMsg_GetCallbackCounter{}) + s.Require().NoError(err) + s.Require().Equal(int(2), len(callbackCounter.Success)) + s.Require().Equal(int(0), len(callbackCounter.Error)) + s.Require().Equal(int(0), len(callbackCounter.Timeout)) + + valResp, err := e2esuite.GRPCQuery[stakingtypes.QueryValidatorResponse](ctx, simd, &stakingtypes.QueryValidatorRequest{ValidatorAddr: validator}) + s.Require().NoError(err) + + s.Require().True(s.Run("verify query result", func() { + s.Require().Nil(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Error) + s.Require().NotNil(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success) + s.Require().Len(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses, 3) + + s.Require().Equal(validator, callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Validator.Validator.Address) + s.Require().Equal(valResp.Validator.Commission.CommissionRates.Rate.BigInt().String(), string(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Validator.Validator.Commission)) + s.Require().Equal(valResp.Validator.Commission.CommissionRates.MaxRate.BigInt().String(), string(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Validator.Validator.MaxCommission)) + s.Require().Equal(valResp.Validator.Commission.CommissionRates.MaxChangeRate.BigInt().String(), string(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Validator.Validator.MaxChangeRate)) + + s.Require().Len(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllValidators.Validators, 2) + s.Require().Contains(callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[1].Staking.AllValidators.Validators, *callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[0].Staking.Validator.Validator) + + s.Require().Equal(simd.Config().Denom, callbackCounter.Success[1].OnAcknowledgementPacketCallback.QueryResult.Success.Responses[2].Staking.BondedDenom.Denom) + })) + })) +} diff --git a/e2e/interchaintestv8/testvalues/values.go b/e2e/interchaintestv8/testvalues/values.go new file mode 100644 index 00000000..8fe4aca7 --- /dev/null +++ b/e2e/interchaintestv8/testvalues/values.go @@ -0,0 +1,19 @@ +package testvalues + +import "time" + +const ( + // StartingTokenAmount is the amount of tokens to give to each user at the start of the testsuite. + StartingTokenAmount int64 = 10_000_000_000 + // FundingAmount is the amount of tokens to give to a user account when funding an address during tests. + FundingAmount int64 = 1_000_000_000 +) + +var ( + // Maximum period to deposit on a proposal. + // This value overrides the default value in the gov module using the `modifyGovV1AppState` function. + MaxDepositPeriod = time.Second * 10 + // Duration of the voting period. + // This value overrides the default value in the gov module using the `modifyGovV1AppState` function. + VotingPeriod = time.Second * 30 +) diff --git a/e2e/interchaintestv8/types/callbackcounter/helpers.go b/e2e/interchaintestv8/types/callbackcounter/helpers.go new file mode 100644 index 00000000..41d16632 --- /dev/null +++ b/e2e/interchaintestv8/types/callbackcounter/helpers.go @@ -0,0 +1,21 @@ +package callbackcounter + +import "encoding/base64" + +// Binary is a thin wrapper around string that is using base64 encoding for []byte. +func (b *Binary) Unwrap() []byte { + res, err := base64.StdEncoding.DecodeString(string(*b)) + if err != nil { + panic(err) + } + return res +} + +// Binary is a thin wrapper around string that is using base64 encoding for []byte. +func (b *Data_Result) Unwrap() []byte { + res, err := base64.StdEncoding.DecodeString(string(*b)) + if err != nil { + panic(err) + } + return res +} diff --git a/e2e/interchaintestv8/types/callbackcounter/msgs.go b/e2e/interchaintestv8/types/callbackcounter/msgs.go index 9c6202dc..ab10e6b6 100644 --- a/e2e/interchaintestv8/types/callbackcounter/msgs.go +++ b/e2e/interchaintestv8/types/callbackcounter/msgs.go @@ -13,6 +13,48 @@ type QueryMsg struct { // GetCallbackCounter returns the callback counter. GetCallbackCounter *QueryMsg_GetCallbackCounter `json:"get_callback_counter,omitempty"` } +type ExecuteMsg_ReceiveIcaCallback IcaControllerCallbackMsg + +/* +A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0 + +The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18) +*/ +type Decimal string + +// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. +type IbcTimeout struct { + Block *IbcTimeoutBlock `json:"block,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` +} + +/* +Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline. + +This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also . +*/ +type Binary string + +type QueryMsg_GetCallbackCounter struct{} + +type IbcEndpoint struct { + ChannelId string `json:"channel_id"` + PortId string `json:"port_id"` +} + +// The response type for the [`cosmwasm_std::StakingQuery`] queries. +type StakingQueryResponse struct { + // Response for the [`cosmwasm_std::StakingQuery::BondedDenom`] query. + BondedDenom *StakingQueryResponse_BondedDenom `json:"bonded_denom,omitempty"` + // Response for the [`cosmwasm_std::StakingQuery::AllDelegations`] query. + AllDelegations *StakingQueryResponse_AllDelegations `json:"all_delegations,omitempty"` + // Response for the [`cosmwasm_std::StakingQuery::Delegation`] query. + Delegation *StakingQueryResponse_Delegation `json:"delegation,omitempty"` + // Response for the [`cosmwasm_std::StakingQuery::AllValidators`] query. + AllValidators *StakingQueryResponse_AllValidators `json:"all_validators,omitempty"` + // Response for the [`cosmwasm_std::StakingQuery::Validator`] query. + Validator *StakingQueryResponse_Validator `json:"validator,omitempty"` +} /* A human readable address. @@ -25,35 +67,91 @@ This type is immutable. If you really need to mutate it (Really? Are you sure?), */ type Addr string -type QueryMsg_GetCallbackCounter struct{} +type Coin struct { + Amount Uint128 `json:"amount"` + Denom string `json:"denom"` +} -// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. -type IbcTimeout struct { - Block IbcTimeoutBlock `json:"block"` - Timestamp Timestamp `json:"timestamp"` +// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. +type IbcOrder string + +const ( + IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" + IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" +) + +// CallbackCounter tracks the number of callbacks in store. +type CallbackCounter struct { + // The successful callbacks. + Success []IcaControllerCallbackMsg `json:"success"` + // The timeout callbacks. The channel is closed after a timeout if the channel is ordered due to the semantics of ordered channels. + Timeout []IcaControllerCallbackMsg `json:"timeout"` + // The erroneous callbacks. + Error []IcaControllerCallbackMsg `json:"error"` } -// IbcChannel defines all information on a channel. This is generally used in the hand-shake process, but can be queried directly. -type IbcChannel struct { - Endpoint IbcEndpoint `json:"endpoint"` - Order IbcOrder `json:"order"` - // Note: in ibcv3 this may be "", in the IbcOpenChannel handshake messages - Version string `json:"version"` - // The connection upon which this channel was created. If this is a multi-hop channel, we only expose the first hop. - ConnectionId string `json:"connection_id"` - CounterpartyEndpoint IbcEndpoint `json:"counterparty_endpoint"` +type DenomMetadataResponse struct { + // The metadata for the queried denom. + Metadata DenomMetadata `json:"metadata"` } -type IbcPacket struct { - // The raw data sent from the other side in the packet - Data Binary `json:"data"` - // identifies the channel and port on the receiving chain. - Dest IbcEndpoint `json:"dest"` - // The sequence number of the packet on the given channel - Sequence int `json:"sequence"` - // identifies the channel and port on the sending chain. - Src IbcEndpoint `json:"src"` - Timeout IbcTimeout `json:"timeout"` +type AllBalanceResponse struct { + // Returns all non-zero coins held by this account. + Amount []Coin `json:"amount"` +} + +/* +A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. + +# Examples + +Use `from` to create instances of this and `u64` to get the value out: + +``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42); + +let b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ``` +*/ +type Uint64 string + +// Instances are created in the querier. +type Validator struct { + /* + The operator address of the validator (e.g. cosmosvaloper1...). See https://github.com/cosmos/cosmos-sdk/blob/v0.47.4/proto/cosmos/staking/v1beta1/staking.proto#L95-L96 for more information. + + This uses `String` instead of `Addr` since the bech32 address prefix is different from the ones that regular user accounts use. + */ + Address string `json:"address"` + Commission Decimal `json:"commission"` + // The maximum daily increase of the commission + MaxChangeRate Decimal `json:"max_change_rate"` + MaxCommission Decimal `json:"max_commission"` +} + +// `Data` is the response to an ibc packet. It either contains a result or an error. +type Data struct { + // Result is the result of a successful transaction. + Result *Data_Result `json:"result,omitempty"` + // Error is the error message of a failed transaction. It is a string of the error message (not base64 encoded). + Error *Data_Error `json:"error,omitempty"` +} + +// The response type for the [`cosmwasm_std::BankQuery`] queries. +type BankQueryResponse struct { + // Response for the [`cosmwasm_std::BankQuery::Supply`] query. + Supply *BankQueryResponse_Supply `json:"supply,omitempty"` + // Response for the [`cosmwasm_std::BankQuery::Balance`] query. + Balance *BankQueryResponse_Balance `json:"balance,omitempty"` + // Response for the [`cosmwasm_std::BankQuery::AllBalances`] query. + AllBalances *BankQueryResponse_AllBalances `json:"all_balances,omitempty"` + // Response for the [`cosmwasm_std::BankQuery::DenomMetadata`] query. + DenomMetadata *BankQueryResponse_DenomMetadata `json:"denom_metadata,omitempty"` + // Response for the [`cosmwasm_std::BankQuery::AllDenomMetadata`] query. + AllDenomMetadata *BankQueryResponse_AllDenomMetadata `json:"all_denom_metadata,omitempty"` +} + +// BondedDenomResponse is data format returned from StakingRequest::BondedDenom query +type BondedDenomResponse struct { + Denom string `json:"denom"` } // IBCTimeoutHeight Height is a monotonically increasing data type that can be compared against another Height for the purposes of updating and freezing clients. Ordering is (revision_number, timeout_height) @@ -63,33 +161,35 @@ type IbcTimeoutBlock struct { // the version that the client is currently on (e.g. after resetting the chain this could increment 1 as height drops to 0) Revision int `json:"revision"` } -type ExecuteMsg_ReceiveIcaCallback IcaControllerCallbackMsg -// IcaControllerCallbackMsg is the type of message that this contract can send to other contracts. -type IcaControllerCallbackMsg struct { - // OnAcknowledgementPacketCallback is the callback that this contract makes to other contracts when it receives an acknowledgement packet. - OnAcknowledgementPacketCallback *IcaControllerCallbackMsg_OnAcknowledgementPacketCallback `json:"on_acknowledgement_packet_callback,omitempty"` - // OnTimeoutPacketCallback is the callback that this contract makes to other contracts when it receives a timeout packet. - OnTimeoutPacketCallback *IcaControllerCallbackMsg_OnTimeoutPacketCallback `json:"on_timeout_packet_callback,omitempty"` - // OnChannelOpenAckCallback is the callback that this contract makes to other contracts when it receives a channel open acknowledgement. - OnChannelOpenAckCallback *IcaControllerCallbackMsg_OnChannelOpenAckCallback `json:"on_channel_open_ack_callback,omitempty"` +// The data format returned from StakingRequest::Validator query +type ValidatorResponse struct { + Validator *Validator `json:"validator,omitempty"` } -// `Data` is the response to an ibc packet. It either contains a result or an error. -type Data struct { - // Result is the result of a successful transaction. - Result *Data_Result `json:"result,omitempty"` - // Error is the error message of a failed transaction. It is a string of the error message (not base64 encoded). - Error *Data_Error `json:"error,omitempty"` +// The response for a successful ICA query. +type IcaQueryResponse struct { + // Response for a [`cosmwasm_std::BankQuery`]. + Bank *IcaQueryResponse_Bank `json:"bank,omitempty"` + // Response for a [`cosmwasm_std::QueryRequest::Stargate`]. Protobuf encoded bytes stored as [`cosmwasm_std::Binary`]. + Stargate *IcaQueryResponse_Stargate `json:"stargate,omitempty"` + // Response for a [`cosmwasm_std::StakingQuery`]. + Staking *IcaQueryResponse_Staking `json:"staking,omitempty"` } -// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. -type IbcOrder string +// Response for the [`cosmwasm_std::StakingQuery::AllDelegations`] query over ICA. +type IcaAllDelegationsResponse struct { + // The delegations. + Delegations []Delegation `json:"delegations"` +} -const ( - IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" - IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" -) +// The result of an ICA query packet. +type IcaQueryResult struct { + // The query was successful and the responses are included. + Success *IcaQueryResult_Success `json:"success,omitempty"` + // The query failed with an error message. The error string often does not contain useful information for the end user. + Error *IcaQueryResult_Error `json:"error,omitempty"` +} // `TxEncoding` is the encoding of the transactions sent to the ICA host. type TxEncoding string @@ -101,12 +201,15 @@ const ( TxEncoding_Proto3Json TxEncoding = "proto3json" ) -/* -Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline. - -This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also . -*/ -type Binary string +// Delegation is the detailed information about a delegation. +type Delegation struct { + // Delegation amount. + Amount Coin `json:"amount"` + // The delegator address. + Delegator string `json:"delegator"` + // A validator address (e.g. cosmosvaloper1...) + Validator string `json:"validator"` +} /* A point in time in nanosecond precision. @@ -122,39 +225,124 @@ let ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(t type Timestamp Uint64 /* -A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. +A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. # Examples -Use `from` to create instances of this and `u64` to get the value out: +Use `from` to create instances of this and `u128` to get the value out: -``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42); +``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123); -let b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ``` +let b = Uint128::from(42u64); assert_eq!(b.u128(), 42); + +let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ``` */ -type Uint64 string +type Uint128 string -type IbcEndpoint struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` +// The data format returned from StakingRequest::AllValidators query +type AllValidatorsResponse struct { + Validators []Validator `json:"validators"` } -// CallbackCounter tracks the number of callbacks in store. -type CallbackCounter struct { - // The erroneous callbacks. - Error []IcaControllerCallbackMsg `json:"error"` - // The successful callbacks. - Success []IcaControllerCallbackMsg `json:"success"` - // The timeout callbacks. The channel is closed after a timeout if the channel is ordered due to the semantics of ordered channels. - Timeout []IcaControllerCallbackMsg `json:"timeout"` +// Response for the [`cosmwasm_std::StakingQuery::Delegation`] query over ICA. +type IcaDelegationResponse struct { + // The delegation response if it exists. + Delegation *Delegation `json:"delegation,omitempty"` } -type IcaControllerCallbackMsg_OnTimeoutPacketCallback struct { - // The original packet that was sent - OriginalPacket IbcPacket `json:"original_packet"` +// Replicates the cosmos-sdk bank module Metadata type +type DenomMetadata struct { + Display string `json:"display"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Uri string `json:"uri"` + UriHash string `json:"uri_hash"` + Base string `json:"base"` + DenomUnits []DenomUnit `json:"denom_units"` + Description string `json:"description"` +} + +type BalanceResponse struct { + // Always returns a Coin with the requested denom. This may be of 0 amount if no such funds. + Amount Coin `json:"amount"` +} + +type IbcPacket struct { + // The raw data sent from the other side in the packet + Data Binary `json:"data"` + // identifies the channel and port on the receiving chain. + Dest IbcEndpoint `json:"dest"` + // The sequence number of the packet on the given channel + Sequence int `json:"sequence"` + // identifies the channel and port on the sending chain. + Src IbcEndpoint `json:"src"` + Timeout IbcTimeout `json:"timeout"` +} + +// `IcaControllerCallbackMsg` is the type of message that this contract can send to other contracts. +type IcaControllerCallbackMsg struct { + // `OnAcknowledgementPacketCallback` is the callback that this contract makes to other contracts when it receives an acknowledgement packet. + OnAcknowledgementPacketCallback *IcaControllerCallbackMsg_OnAcknowledgementPacketCallback `json:"on_acknowledgement_packet_callback,omitempty"` + // `OnTimeoutPacketCallback` is the callback that this contract makes to other contracts when it receives a timeout packet. + OnTimeoutPacketCallback *IcaControllerCallbackMsg_OnTimeoutPacketCallback `json:"on_timeout_packet_callback,omitempty"` + // `OnChannelOpenAckCallback` is the callback that this contract makes to other contracts when it receives a channel open acknowledgement. + OnChannelOpenAckCallback *IcaControllerCallbackMsg_OnChannelOpenAckCallback `json:"on_channel_open_ack_callback,omitempty"` +} + +// IbcChannel defines all information on a channel. This is generally used in the hand-shake process, but can be queried directly. +type IbcChannel struct { + Order IbcOrder `json:"order"` + // Note: in ibcv3 this may be "", in the IbcOpenChannel handshake messages + Version string `json:"version"` + // The connection upon which this channel was created. If this is a multi-hop channel, we only expose the first hop. + ConnectionId string `json:"connection_id"` + CounterpartyEndpoint IbcEndpoint `json:"counterparty_endpoint"` + Endpoint IbcEndpoint `json:"endpoint"` +} + +type SupplyResponse struct { + // Always returns a Coin with the requested denom. This will be of zero amount if the denom does not exist. + Amount Coin `json:"amount"` +} + +// Replicates the cosmos-sdk bank module DenomUnit type +type DenomUnit struct { + Exponent int `json:"exponent"` + Aliases []string `json:"aliases"` + Denom string `json:"denom"` +} + +type AllDenomMetadataResponse struct { + NextKey *Binary `json:"next_key,omitempty"` + // Always returns metadata for all token denoms on the base chain. + Metadata []DenomMetadata `json:"metadata"` +} + +type IcaQueryResult_Success struct { + // The height of the block at which the queries were executed on the counterparty chain. + Height int `json:"height"` + // The responses to the queries. + Responses []IcaQueryResponse `json:"responses"` +} +type Data_Result Binary + +type IcaControllerCallbackMsg_OnAcknowledgementPacketCallback struct { // The relayer that submitted acknowledgement packet Relayer Addr `json:"relayer"` + // The deserialized ICA acknowledgement data + IcaAcknowledgement Data `json:"ica_acknowledgement"` + // The original packet that was sent + OriginalPacket IbcPacket `json:"original_packet"` + // The responses to the queries. + QueryResult *IcaQueryResult `json:"query_result,omitempty"` } +type BankQueryResponse_Supply SupplyResponse +type BankQueryResponse_DenomMetadata DenomMetadataResponse +type IcaQueryResponse_Staking StakingQueryResponse +type StakingQueryResponse_AllDelegations IcaAllDelegationsResponse +type BankQueryResponse_AllBalances AllBalanceResponse +type StakingQueryResponse_Validator ValidatorResponse +type StakingQueryResponse_AllValidators AllValidatorsResponse type IcaControllerCallbackMsg_OnChannelOpenAckCallback struct { // The tx encoding this ICA channel uses. @@ -164,15 +352,26 @@ type IcaControllerCallbackMsg_OnChannelOpenAckCallback struct { // The address of the interchain account that was created. IcaAddress string `json:"ica_address"` } -type Data_Result Binary - -type Data_Error string +type BankQueryResponse_Balance BalanceResponse +type StakingQueryResponse_BondedDenom BondedDenomResponse -type IcaControllerCallbackMsg_OnAcknowledgementPacketCallback struct { - // The relayer that submitted acknowledgement packet - Relayer Addr `json:"relayer"` - // The deserialized ICA acknowledgement data - IcaAcknowledgement Data `json:"ica_acknowledgement"` +type IcaControllerCallbackMsg_OnTimeoutPacketCallback struct { // The original packet that was sent OriginalPacket IbcPacket `json:"original_packet"` + // The relayer that submitted acknowledgement packet + Relayer Addr `json:"relayer"` } +type StakingQueryResponse_Delegation IcaDelegationResponse + +type Data_Error string +type BankQueryResponse_AllDenomMetadata AllDenomMetadataResponse +type IcaQueryResponse_Bank BankQueryResponse + +type IcaQueryResponse_Stargate struct { + // The response bytes. + Data Binary `json:"data"` + // The query grpc method + Path string `json:"path"` +} + +type IcaQueryResult_Error string diff --git a/e2e/interchaintestv8/types/cwicacontroller/helpers.go b/e2e/interchaintestv8/types/cwicacontroller/helpers.go index ca8328e8..220dbcd7 100644 --- a/e2e/interchaintestv8/types/cwicacontroller/helpers.go +++ b/e2e/interchaintestv8/types/cwicacontroller/helpers.go @@ -34,3 +34,16 @@ func NewExecuteMsg_SendCosmosMsgs_FromProto(msgs []proto.Message, memo *string, }, } } + +// NewStargateQuery_FromProto creates a new QueryRequest_for_Empty_Stargate +func NewStargateQuery_FromProto(path string, data proto.Message) *QueryRequest_for_Empty_Stargate { + dataBz, err := proto.Marshal(data) + if err != nil { + panic(err) + } + + return &QueryRequest_for_Empty_Stargate{ + Data: Binary(base64.StdEncoding.EncodeToString(dataBz)), + Path: path, + } +} diff --git a/e2e/interchaintestv8/types/cwicacontroller/msgs.go b/e2e/interchaintestv8/types/cwicacontroller/msgs.go index eee82161..ae307b3a 100644 --- a/e2e/interchaintestv8/types/cwicacontroller/msgs.go +++ b/e2e/interchaintestv8/types/cwicacontroller/msgs.go @@ -39,71 +39,152 @@ type QueryMsg struct { Ownership *QueryMsg_Ownership `json:"ownership,omitempty"` } -type ExecuteMsg_UpdateCallbackAddress struct { - // The new callback address. If not specified, then no callbacks are sent. - CallbackAddress *string `json:"callback_address,omitempty"` +/* +A human readable address. + +In Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length. + +This type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances. + +This type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance. +*/ +type Addr string +type ExecuteMsg_UpdateOwnership Action + +type BankQuery struct { + // This calls into the native bank module for querying the total supply of one denomination. It does the same as the SupplyOf call in Cosmos SDK's RPC API. Return value is of type SupplyResponse. + Supply *BankQuery_Supply `json:"supply,omitempty"` + // This calls into the native bank module for one denomination Return value is BalanceResponse + Balance *BankQuery_Balance `json:"balance,omitempty"` + // This calls into the native bank module for all denominations. Note that this may be much more expensive than Balance and should be avoided if possible. Return value is AllBalanceResponse. + AllBalances *BankQuery_AllBalances `json:"all_balances,omitempty"` + // This calls into the native bank module for querying metadata for a specific bank token. Return value is DenomMetadataResponse + DenomMetadata *BankQuery_DenomMetadata `json:"denom_metadata,omitempty"` + // This calls into the native bank module for querying metadata for all bank tokens that have a metadata entry. Return value is AllDenomMetadataResponse + AllDenomMetadata *BankQuery_AllDenomMetadata `json:"all_denom_metadata,omitempty"` } -// Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future) -type Expiration struct { - // AtHeight will expire when `env.block.height` >= height - AtHeight *Expiration_AtHeight `json:"at_height,omitempty"` - // AtTime will expire when `env.block.time` >= time - AtTime *Expiration_AtTime `json:"at_time,omitempty"` - // Never will never expire. Used to express the empty variant - Never *Expiration_Never `json:"never,omitempty"` +type Coin struct { + Amount Uint128 `json:"amount"` + Denom string `json:"denom"` +} + +type QueryMsg_Ownership struct{} + +// The contract's ownership info +type Ownership_for_String struct { + // The contract's current owner. `None` if the ownership has been renounced. + Owner *string `json:"owner,omitempty"` + // The deadline for the pending owner to accept the ownership. `None` if there isn't a pending ownership transfer, or if a transfer exists and it doesn't have a deadline. + PendingExpiry *Expiration `json:"pending_expiry,omitempty"` + // The account who has been proposed to take over the ownership. `None` if there isn't a pending ownership transfer. + PendingOwner *string `json:"pending_owner,omitempty"` +} + +type VoteOption string + +const ( + VoteOption_Yes VoteOption = "yes" + VoteOption_No VoteOption = "no" + VoteOption_Abstain VoteOption = "abstain" + VoteOption_NoWithVeto VoteOption = "no_with_veto" +) + +// Simplified version of the PageRequest type for pagination from the cosmos-sdk +type PageRequest struct { + Reverse bool `json:"reverse"` + Key *Binary `json:"key,omitempty"` + Limit int `json:"limit"` } /* -A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0 +The message types of the staking module. -The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18) +See https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto */ -type Decimal string +type StakingMsg struct { + // This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address. + Delegate *StakingMsg_Delegate `json:"delegate,omitempty"` + // This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address. + Undelegate *StakingMsg_Undelegate `json:"undelegate,omitempty"` + // This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address. + Redelegate *StakingMsg_Redelegate `json:"redelegate,omitempty"` +} + +// The options needed to initialize the IBC channel. +type ChannelOpenInitOptions struct { + // The order of the channel. If not specified, [`IbcOrder::Ordered`] is used. [`IbcOrder::Unordered`] is only supported if the counterparty chain is using `ibc-go` v8.1.0 or later. + ChannelOrdering *IbcOrder `json:"channel_ordering,omitempty"` + // The connection id on this chain. + ConnectionId string `json:"connection_id"` + // The counterparty connection id on the counterparty chain. + CounterpartyConnectionId string `json:"counterparty_connection_id"` + // The counterparty port id. If not specified, [`crate::ibc::types::keys::HOST_PORT_ID`] is used. Currently, this contract only supports the host port. + CounterpartyPortId *string `json:"counterparty_port_id,omitempty"` +} + +// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. +type IbcOrder string + +const ( + IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" + IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" +) /* -A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. +Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline. -# Examples +This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also . +*/ +type Binary string -Use `from` to create instances of this and `u128` to get the value out: +// IBCTimeoutHeight Height is a monotonically increasing data type that can be compared against another Height for the purposes of updating and freezing clients. Ordering is (revision_number, timeout_height) +type IbcTimeoutBlock struct { + // block height after which the packet times out. the height within the given revision + Height int `json:"height"` + // the version that the client is currently on (e.g. after resetting the chain this could increment 1 as height drops to 0) + Revision int `json:"revision"` +} -``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123); +// These are queries to the various IBC modules to see the state of the contract's IBC connection. These will return errors if the contract is not "ibc enabled" +type IbcQuery struct { + /* + Gets the Port ID the current contract is bound to. -let b = Uint128::from(42u64); assert_eq!(b.u128(), 42); + Returns a `PortIdResponse`. + */ + PortId *IbcQuery_PortId `json:"port_id,omitempty"` + /* + Lists all channels that are bound to a given port. If `port_id` is omitted, this list all channels bound to the contract's port. -let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ``` -*/ -type Uint128 string + Returns a `ListChannelsResponse`. + */ + ListChannels *IbcQuery_ListChannels `json:"list_channels,omitempty"` + /* + Lists all information for a (portID, channelID) pair. If port_id is omitted, it will default to the contract's own channel. (To save a PortId{} call) + + Returns a `ChannelResponse`. + */ + Channel *IbcQuery_Channel `json:"channel,omitempty"` +} // IbcChannel defines all information on a channel. This is generally used in the hand-shake process, but can be queried directly. type IbcChannel struct { + // Note: in ibcv3 this may be "", in the IbcOpenChannel handshake messages + Version string `json:"version"` // The connection upon which this channel was created. If this is a multi-hop channel, we only expose the first hop. ConnectionId string `json:"connection_id"` CounterpartyEndpoint IbcEndpoint `json:"counterparty_endpoint"` Endpoint IbcEndpoint `json:"endpoint"` Order IbcOrder `json:"order"` - // Note: in ibcv3 this may be "", in the IbcOpenChannel handshake messages - Version string `json:"version"` } -// The contract's ownership info -type Ownership_for_String struct { - // The contract's current owner. `None` if the ownership has been renounced. - Owner *string `json:"owner,omitempty"` - // The deadline for the pending owner to accept the ownership. `None` if there isn't a pending ownership transfer, or if a transfer exists and it doesn't have a deadline. - PendingExpiry *Expiration `json:"pending_expiry,omitempty"` - // The account who has been proposed to take over the ownership. `None` if there isn't a pending ownership transfer. - PendingOwner *string `json:"pending_owner,omitempty"` -} - -type ExecuteMsg_SendCosmosMsgs struct { - // The stargate messages to convert and send to the ICA host. - Messages []CosmosMsg_for_Empty `json:"messages"` - // Optional memo to include in the ibc packet. - PacketMemo *string `json:"packet_memo,omitempty"` - // Optional timeout in seconds to include with the ibc packet. If not specified, the [default timeout](crate::ibc::types::packet::DEFAULT_TIMEOUT_SECONDS) is used. - TimeoutSeconds *int `json:"timeout_seconds,omitempty"` +// State is the state of the contract. +type State struct { + // The address of the callback contract. + CallbackAddress *Addr `json:"callback_address,omitempty"` + // The Interchain Account (ICA) info needed to send packets. This is set during the handshake. + IcaInfo *IcaInfo `json:"ica_info,omitempty"` } /* @@ -132,46 +213,6 @@ type GovMsg struct { VoteWeighted *GovMsg_VoteWeighted `json:"vote_weighted,omitempty"` } -type QueryMsg_GetContractState struct{} - -// Status is the status of an IBC channel. -type Status string - -const ( - // Uninitialized is the default state of the channel. - Status_StateUninitializedUnspecified Status = "STATE_UNINITIALIZED_UNSPECIFIED" - // Init is the state of the channel when it is created. - Status_StateInit Status = "STATE_INIT" - // TryOpen is the state of the channel when it is trying to open. - Status_StateTryopen Status = "STATE_TRYOPEN" - // Open is the state of the channel when it is open. - Status_StateOpen Status = "STATE_OPEN" - // Closed is the state of the channel when it is closed. - Status_StateClosed Status = "STATE_CLOSED" - // The channel has just accepted the upgrade handshake attempt and is flushing in-flight packets. Added in `ibc-go` v8.1.0. - Status_StateFlushing Status = "STATE_FLUSHING" - // The channel has just completed flushing any in-flight packets. Added in `ibc-go` v8.1.0. - Status_StateFlushcomplete Status = "STATE_FLUSHCOMPLETE" -) - -// The options needed to initialize the IBC channel. -type ChannelOpenInitOptions struct { - // The order of the channel. If not specified, [`IbcOrder::Ordered`] is used. [`IbcOrder::Unordered`] is only supported if the counterparty chain is using `ibc-go` v8.1.0 or later. - ChannelOrdering *IbcOrder `json:"channel_ordering,omitempty"` - // The connection id on this chain. - ConnectionId string `json:"connection_id"` - // The counterparty connection id on the counterparty chain. - CounterpartyConnectionId string `json:"counterparty_connection_id"` - // The counterparty port id. If not specified, [`crate::ibc::types::keys::HOST_PORT_ID`] is used. Currently, this contract only supports the host port. - CounterpartyPortId *string `json:"counterparty_port_id,omitempty"` -} - -// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. -type IbcTimeout struct { - Block *IbcTimeoutBlock `json:"block,omitempty"` - Timestamp *Timestamp `json:"timestamp,omitempty"` -} - /* A point in time in nanosecond precision. @@ -185,46 +226,132 @@ let ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(t */ type Timestamp Uint64 +// `TxEncoding` is the encoding of the transactions sent to the ICA host. +type TxEncoding string + +const ( + // `Protobuf` is the protobuf serialization of the CosmosSDK's Any. + TxEncoding_Proto3 TxEncoding = "proto3" + // `Proto3Json` is the json serialization of the CosmosSDK's Any. + TxEncoding_Proto3Json TxEncoding = "proto3json" +) + +type ExecuteMsg_CloseChannel struct{} + +type ExecuteMsg_SendCosmosMsgs struct { + // The stargate messages to convert and send to the ICA host. + Messages []CosmosMsg_for_Empty `json:"messages"` + // Optional memo to include in the ibc packet. + PacketMemo *string `json:"packet_memo,omitempty"` + // The stargate queries to convert and send to the ICA host. The queries are executed after the messages. + Queries []QueryRequest_for_Empty `json:"queries"` + // Optional timeout in seconds to include with the ibc packet. If not specified, the [default timeout](crate::ibc::types::packet::DEFAULT_TIMEOUT_SECONDS) is used. + TimeoutSeconds *int `json:"timeout_seconds,omitempty"` +} + +type QueryMsg_GetChannel struct{} + +type IbcEndpoint struct { + ChannelId string `json:"channel_id"` + PortId string `json:"port_id"` +} + +// IcaInfo is the ICA address and channel ID. +type IcaInfo struct { + IcaAddress string `json:"ica_address"` + ChannelId string `json:"channel_id"` + Encoding TxEncoding `json:"encoding"` +} + +type ExecuteMsg_CreateChannel struct { + // The options to initialize the IBC channel. If not specified, the options specified in the last channel creation are used. Must be `None` if the sender is not the owner. + ChannelOpenInitOptions *ChannelOpenInitOptions `json:"channel_open_init_options,omitempty"` +} + +type DistributionQuery struct { + // See + DelegatorWithdrawAddress *DistributionQuery_DelegatorWithdrawAddress `json:"delegator_withdraw_address,omitempty"` + // See + DelegationRewards *DistributionQuery_DelegationRewards `json:"delegation_rewards,omitempty"` + // See + DelegationTotalRewards *DistributionQuery_DelegationTotalRewards `json:"delegation_total_rewards,omitempty"` + // See + DelegatorValidators *DistributionQuery_DelegatorValidators `json:"delegator_validators,omitempty"` +} + /* -A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. +A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. # Examples -Use `from` to create instances of this and `u64` to get the value out: +Use `from` to create instances of this and `u128` to get the value out: -``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42); +``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123); -let b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ``` +let b = Uint128::from(42u64); assert_eq!(b.u128(), 42); + +let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ``` */ -type Uint64 string +type Uint128 string + +type WeightedVoteOption struct { + Option VoteOption `json:"option"` + Weight Decimal `json:"weight"` +} + +type ExecuteMsg_UpdateCallbackAddress struct { + // The new callback address. If not specified, then no callbacks are sent. + CallbackAddress *string `json:"callback_address,omitempty"` +} + +// Actions that can be taken to alter the contract's ownership +type Action interface { + Implements_Action() +} + +var _ Action = (*Action_TransferOwnership)(nil) + +type Action_TransferOwnership struct { + Expiry *Expiration `json:"expiry,omitempty"` + NewOwner string `json:"new_owner"` +} + +func (*Action_TransferOwnership) Implements_Action() {} + +var _ Action = (*Action_AcceptOwnership)(nil) + +type Action_AcceptOwnership string /* -Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline. +Accept the pending ownership transfer. -This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also . +Can only be called by the pending owner. */ -type Binary string +const Action_AcceptOwnership_Value Action_AcceptOwnership = "accept_ownership" -/* -A human readable address. +func (*Action_AcceptOwnership) Implements_Action() {} -In Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length. +var _ Action = (*Action_RenounceOwnership)(nil) -This type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances. +type Action_RenounceOwnership string -This type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance. +/* +Give up the contract's ownership and the possibility of appointing a new owner. + +Can only be invoked by the contract's current owner. + +Any existing pending ownership transfer is canceled. */ -type Addr string +const Action_RenounceOwnership_Value Action_RenounceOwnership = "renounce_ownership" -// State is the state of the contract. -type State_2 struct { - // The address of the callback contract. - CallbackAddress *Addr `json:"callback_address,omitempty"` - // The Interchain Account (ICA) info needed to send packets. This is set during the handshake. - IcaInfo *IcaInfo `json:"ica_info,omitempty"` -} +func (*Action_RenounceOwnership) Implements_Action() {} -type ExecuteMsg_CloseChannel struct{} +/* +An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message. + +It is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451) +*/ +type Empty struct{} // These are messages in the IBC lifecycle. Only usable by IBC-enabled contracts (contracts that directly speak the IBC protocol via 6 entry points) type IbcMsg struct { @@ -236,18 +363,23 @@ type IbcMsg struct { CloseChannel *IbcMsg_CloseChannel `json:"close_channel,omitempty"` } -type QueryMsg_GetChannel struct{} +type WasmQuery struct { + // this queries the public API of another contract at a known address (with known ABI) Return value is whatever the contract returns (caller should know), wrapped in a ContractResult that is JSON encoded. + Smart *WasmQuery_Smart `json:"smart,omitempty"` + // this queries the raw kv-store of the contract. returns the raw, unparsed data stored at that key, which may be an empty vector if not present + Raw *WasmQuery_Raw `json:"raw,omitempty"` + // Returns a [`ContractInfoResponse`] with metadata on the contract from the runtime + ContractInfo *WasmQuery_ContractInfo `json:"contract_info,omitempty"` + // Returns a [`CodeInfoResponse`] with metadata of the code + CodeInfo *WasmQuery_CodeInfo `json:"code_info,omitempty"` +} -type CosmosMsg_for_Empty struct { - Bank *CosmosMsg_for_Empty_Bank `json:"bank,omitempty"` - Custom *CosmosMsg_for_Empty_Custom `json:"custom,omitempty"` - Staking *CosmosMsg_for_Empty_Staking `json:"staking,omitempty"` - Distribution *CosmosMsg_for_Empty_Distribution `json:"distribution,omitempty"` - // A Stargate message encoded the same way as a protobuf [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md) - Stargate *CosmosMsg_for_Empty_Stargate `json:"stargate,omitempty"` - Ibc *CosmosMsg_for_Empty_Ibc `json:"ibc,omitempty"` - Wasm *CosmosMsg_for_Empty_Wasm `json:"wasm,omitempty"` - Gov *CosmosMsg_for_Empty_Gov `json:"gov,omitempty"` +// State is the state of the IBC application's channel. This application only supports one channel. +type ChannelState struct { + // The IBC channel, as defined by cosmwasm. + Channel IbcChannel `json:"channel"` + // The status of the channel. + ChannelStatus ChannelStatus `json:"channel_status"` } /* @@ -290,94 +422,6 @@ type WasmMsg struct { ClearAdmin *WasmMsg_ClearAdmin `json:"clear_admin,omitempty"` } -/* -An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message. - -It is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451) -*/ -type Empty struct{} - -// IcaInfo is the ICA address and channel ID. -type IcaInfo struct { - ChannelId string `json:"channel_id"` - Encoding TxEncoding `json:"encoding"` - IcaAddress string `json:"ica_address"` -} - -type ExecuteMsg_CreateChannel struct { - // The options to initialize the IBC channel. If not specified, the options specified in the last channel creation are used. Must be `None` if the sender is not the owner. - ChannelOpenInitOptions *ChannelOpenInitOptions `json:"channel_open_init_options,omitempty"` -} - -type Coin struct { - Amount Uint128 `json:"amount"` - Denom string `json:"denom"` -} - -type VoteOption string - -const ( - VoteOption_Yes VoteOption = "yes" - VoteOption_No VoteOption = "no" - VoteOption_Abstain VoteOption = "abstain" - VoteOption_NoWithVeto VoteOption = "no_with_veto" -) - -type IbcEndpoint struct { - ChannelId string `json:"channel_id"` - PortId string `json:"port_id"` -} - -// State is the state of the IBC application's channel. This application only supports one channel. -type State struct { - // The IBC channel, as defined by cosmwasm. - Channel IbcChannel `json:"channel"` - // The status of the channel. - ChannelStatus Status `json:"channel_status"` -} - -// Actions that can be taken to alter the contract's ownership -type Action interface { - Implements_Action() -} - -var _ Action = (*Action_TransferOwnership)(nil) - -type Action_TransferOwnership struct { - Expiry *Expiration `json:"expiry,omitempty"` - NewOwner string `json:"new_owner"` -} - -func (*Action_TransferOwnership) Implements_Action() {} - -var _ Action = (*Action_AcceptOwnership)(nil) - -type Action_AcceptOwnership string - -/* -Accept the pending ownership transfer. - -Can only be called by the pending owner. -*/ -const Action_AcceptOwnership_Value Action_AcceptOwnership = "accept_ownership" - -func (*Action_AcceptOwnership) Implements_Action() {} - -var _ Action = (*Action_RenounceOwnership)(nil) - -type Action_RenounceOwnership string - -/* -Give up the contract's ownership and the possibility of appointing a new owner. - -Can only be invoked by the contract's current owner. - -Any existing pending ownership transfer is canceled. -*/ -const Action_RenounceOwnership_Value Action_RenounceOwnership = "renounce_ownership" - -func (*Action_RenounceOwnership) Implements_Action() {} - /* The message types of the bank module. @@ -394,37 +438,95 @@ type BankMsg struct { Burn *BankMsg_Burn `json:"burn,omitempty"` } -// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. -type IbcOrder string +type QueryRequest_for_Empty struct { + Bank *QueryRequest_for_Empty_Bank `json:"bank,omitempty"` + Custom *QueryRequest_for_Empty_Custom `json:"custom,omitempty"` + Staking *QueryRequest_for_Empty_Staking `json:"staking,omitempty"` + Distribution *QueryRequest_for_Empty_Distribution `json:"distribution,omitempty"` + // A Stargate query is encoded the same way as abci_query, with path and protobuf encoded request data. The format is defined in [ADR-21](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-021-protobuf-query-encoding.md). The response is protobuf encoded data directly without a JSON response wrapper. The caller is responsible for compiling the proper protobuf definitions for both requests and responses. + Stargate *QueryRequest_for_Empty_Stargate `json:"stargate,omitempty"` + Ibc *QueryRequest_for_Empty_Ibc `json:"ibc,omitempty"` + Wasm *QueryRequest_for_Empty_Wasm `json:"wasm,omitempty"` +} + +type StakingQuery struct { + // Returns the denomination that can be bonded (if there are multiple native tokens on the chain) + BondedDenom *StakingQuery_BondedDenom `json:"bonded_denom,omitempty"` + // AllDelegations will return all delegations by the delegator + AllDelegations *StakingQuery_AllDelegations `json:"all_delegations,omitempty"` + // Delegation will return more detailed info on a particular delegation, defined by delegator/validator pair + Delegation *StakingQuery_Delegation `json:"delegation,omitempty"` + /* + Returns all validators in the currently active validator set. + + The query response type is `AllValidatorsResponse`. + */ + AllValidators *StakingQuery_AllValidators `json:"all_validators,omitempty"` + /* + Returns the validator at the given address. Returns None if the validator is not part of the currently active validator set. + + The query response type is `ValidatorResponse`. + */ + Validator *StakingQuery_Validator `json:"validator,omitempty"` +} + +// Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future) +type Expiration struct { + // AtHeight will expire when `env.block.height` >= height + AtHeight *Expiration_AtHeight `json:"at_height,omitempty"` + // AtTime will expire when `env.block.time` >= time + AtTime *Expiration_AtTime `json:"at_time,omitempty"` + // Never will never expire. Used to express the empty variant + Never *Expiration_Never `json:"never,omitempty"` +} + +type QueryMsg_GetContractState struct{} + +// Status is the status of an IBC channel. +type ChannelStatus string const ( - IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" - IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" + // Uninitialized is the default state of the channel. + ChannelStatus_StateUninitializedUnspecified ChannelStatus = "STATE_UNINITIALIZED_UNSPECIFIED" + // Init is the state of the channel when it is created. + ChannelStatus_StateInit ChannelStatus = "STATE_INIT" + // TryOpen is the state of the channel when it is trying to open. + ChannelStatus_StateTryopen ChannelStatus = "STATE_TRYOPEN" + // Open is the state of the channel when it is open. + ChannelStatus_StateOpen ChannelStatus = "STATE_OPEN" + // Closed is the state of the channel when it is closed. + ChannelStatus_StateClosed ChannelStatus = "STATE_CLOSED" + // The channel has just accepted the upgrade handshake attempt and is flushing in-flight packets. Added in `ibc-go` v8.1.0. + ChannelStatus_StateFlushing ChannelStatus = "STATE_FLUSHING" + // The channel has just completed flushing any in-flight packets. Added in `ibc-go` v8.1.0. + ChannelStatus_StateFlushcomplete ChannelStatus = "STATE_FLUSHCOMPLETE" ) -type ExecuteMsg_UpdateOwnership Action +/* +A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0 + +The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18) +*/ +type Decimal string -// IBCTimeoutHeight Height is a monotonically increasing data type that can be compared against another Height for the purposes of updating and freezing clients. Ordering is (revision_number, timeout_height) -type IbcTimeoutBlock struct { - // block height after which the packet times out. the height within the given revision - Height int `json:"height"` - // the version that the client is currently on (e.g. after resetting the chain this could increment 1 as height drops to 0) - Revision int `json:"revision"` +// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. +type IbcTimeout struct { + Block *IbcTimeoutBlock `json:"block,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` } /* -The message types of the staking module. +A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. -See https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto +# Examples + +Use `from` to create instances of this and `u64` to get the value out: + +``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42); + +let b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ``` */ -type StakingMsg struct { - // This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address. - Delegate *StakingMsg_Delegate `json:"delegate,omitempty"` - // This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address. - Undelegate *StakingMsg_Undelegate `json:"undelegate,omitempty"` - // This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address. - Redelegate *StakingMsg_Redelegate `json:"redelegate,omitempty"` -} +type Uint64 string /* The message types of the distribution module. @@ -440,77 +542,88 @@ type DistributionMsg struct { FundCommunityPool *DistributionMsg_FundCommunityPool `json:"fund_community_pool,omitempty"` } -type WeightedVoteOption struct { - Weight Decimal `json:"weight"` - Option VoteOption `json:"option"` +type CosmosMsg_for_Empty struct { + Bank *CosmosMsg_for_Empty_Bank `json:"bank,omitempty"` + Custom *CosmosMsg_for_Empty_Custom `json:"custom,omitempty"` + Staking *CosmosMsg_for_Empty_Staking `json:"staking,omitempty"` + Distribution *CosmosMsg_for_Empty_Distribution `json:"distribution,omitempty"` + // A Stargate message encoded the same way as a protobuf [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md) + Stargate *CosmosMsg_for_Empty_Stargate `json:"stargate,omitempty"` + Ibc *CosmosMsg_for_Empty_Ibc `json:"ibc,omitempty"` + Wasm *CosmosMsg_for_Empty_Wasm `json:"wasm,omitempty"` + Gov *CosmosMsg_for_Empty_Gov `json:"gov,omitempty"` } -type QueryMsg_Ownership struct{} - -// `TxEncoding` is the encoding of the transactions sent to the ICA host. -type TxEncoding string - -const ( - // `Protobuf` is the protobuf serialization of the CosmosSDK's Any. - TxEncoding_Proto3 TxEncoding = "proto3" - // `Proto3Json` is the json serialization of the CosmosSDK's Any. - TxEncoding_Proto3Json TxEncoding = "proto3json" -) +type WasmMsg_Migrate struct { + ContractAddr string `json:"contract_addr"` + // msg is the json-encoded MigrateMsg struct that will be passed to the new code + Msg Binary `json:"msg"` + // the code_id of the new logic to place in the given contract + NewCodeId int `json:"new_code_id"` +} +type QueryRequest_for_Empty_Distribution DistributionQuery -type GovMsg_VoteWeighted struct { - Options []WeightedVoteOption `json:"options"` - ProposalId int `json:"proposal_id"` +type DistributionQuery_DelegatorValidators struct { + DelegatorAddress string `json:"delegator_address"` } -type CosmosMsg_for_Empty_Wasm WasmMsg +type Expiration_AtTime Timestamp +type CosmosMsg_for_Empty_Distribution DistributionMsg type IbcMsg_SendPacket struct { - // when packet times out, measured on remote chain - Timeout IbcTimeout `json:"timeout"` ChannelId string `json:"channel_id"` Data Binary `json:"data"` -} - -type IbcMsg_Transfer struct { - // address on the remote chain to receive these tokens - ToAddress string `json:"to_address"` - // packet data only supports one coin https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/applications/transfer/v1/transfer.proto#L11-L20 - Amount Coin `json:"amount"` - // existing channel to send the tokens over - ChannelId string `json:"channel_id"` // when packet times out, measured on remote chain Timeout IbcTimeout `json:"timeout"` } -type BankMsg_Burn struct { - Amount []Coin `json:"amount"` +type DistributionQuery_DelegationRewards struct { + DelegatorAddress string `json:"delegator_address"` + ValidatorAddress string `json:"validator_address"` } -type WasmMsg_Migrate struct { +type StakingQuery_Validator struct { + // The validator's address (e.g. (e.g. cosmosvaloper1...)) + Address string `json:"address"` +} + +type WasmMsg_UpdateAdmin struct { + Admin string `json:"admin"` ContractAddr string `json:"contract_addr"` - // msg is the json-encoded MigrateMsg struct that will be passed to the new code - Msg Binary `json:"msg"` - // the code_id of the new logic to place in the given contract - NewCodeId int `json:"new_code_id"` } -type CosmosMsg_for_Empty_Stargate struct { - TypeUrl string `json:"type_url"` - Value Binary `json:"value"` +type StakingQuery_Delegation struct { + Delegator string `json:"delegator"` + Validator string `json:"validator"` } -type Expiration_AtHeight int -type CosmosMsg_for_Empty_Distribution DistributionMsg +type DistributionMsg_SetWithdrawAddress struct { + // The `withdraw_address` + Address string `json:"address"` +} -type IbcMsg_CloseChannel struct { - ChannelId string `json:"channel_id"` +type StakingMsg_Undelegate struct { + Amount Coin `json:"amount"` + Validator string `json:"validator"` } -type CosmosMsg_for_Empty_Ibc IbcMsg -type CosmosMsg_for_Empty_Staking StakingMsg -type CosmosMsg_for_Empty_Custom Empty -type WasmMsg_UpdateAdmin struct { - Admin string `json:"admin"` - ContractAddr string `json:"contract_addr"` +type DistributionMsg_WithdrawDelegatorReward struct { + // The `validator_address` + Validator string `json:"validator"` +} + +type Expiration_Never struct{} + +type BankQuery_Balance struct { + Address string `json:"address"` + Denom string `json:"denom"` +} + +type DistributionQuery_DelegatorWithdrawAddress struct { + DelegatorAddress string `json:"delegator_address"` +} + +type BankMsg_Burn struct { + Amount []Coin `json:"amount"` } type WasmMsg_Instantiate2 struct { @@ -527,60 +640,92 @@ type WasmMsg_Instantiate2 struct { Msg Binary `json:"msg"` Salt Binary `json:"salt"` } +type QueryRequest_for_Empty_Custom Empty -type StakingMsg_Undelegate struct { - Amount Coin `json:"amount"` - Validator string `json:"validator"` +type QueryRequest_for_Empty_Stargate struct { + // this is the expected protobuf message type (not any), binary encoded + Data Binary `json:"data"` + // this is the fully qualified service path used for routing, eg. custom/cosmos_sdk.x.bank.v1.Query/QueryBalance + Path string `json:"path"` } -type StakingMsg_Delegate struct { - Amount Coin `json:"amount"` - Validator string `json:"validator"` +type WasmQuery_Smart struct { + ContractAddr string `json:"contract_addr"` + // msg is the json-encoded QueryMsg struct + Msg Binary `json:"msg"` } +type QueryRequest_for_Empty_Bank BankQuery +type QueryRequest_for_Empty_Wasm WasmQuery -type DistributionMsg_SetWithdrawAddress struct { - // The `withdraw_address` - Address string `json:"address"` +type StakingQuery_AllValidators struct{} + +type DistributionQuery_DelegationTotalRewards struct { + DelegatorAddress string `json:"delegator_address"` } -type CosmosMsg_for_Empty_Bank BankMsg type WasmMsg_Execute struct { - ContractAddr string `json:"contract_addr"` - Funds []Coin `json:"funds"` // msg is the json-encoded ExecuteMsg struct (as raw Binary) Msg Binary `json:"msg"` + ContractAddr string `json:"contract_addr"` + Funds []Coin `json:"funds"` } -type WasmMsg_ClearAdmin struct { - ContractAddr string `json:"contract_addr"` +type WasmQuery_CodeInfo struct { + CodeId int `json:"code_id"` } +type CosmosMsg_for_Empty_Bank BankMsg -type DistributionMsg_WithdrawDelegatorReward struct { - // The `validator_address` - Validator string `json:"validator"` +type IbcMsg_Transfer struct { + // existing channel to send the tokens over + ChannelId string `json:"channel_id"` + // when packet times out, measured on remote chain + Timeout IbcTimeout `json:"timeout"` + // address on the remote chain to receive these tokens + ToAddress string `json:"to_address"` + // packet data only supports one coin https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/applications/transfer/v1/transfer.proto#L11-L20 + Amount Coin `json:"amount"` +} + +type IbcMsg_CloseChannel struct { + ChannelId string `json:"channel_id"` } + +type BankQuery_DenomMetadata struct { + Denom string `json:"denom"` +} +type CosmosMsg_for_Empty_Ibc IbcMsg type CosmosMsg_for_Empty_Gov GovMsg -type GovMsg_Vote struct { - /* - The vote option. +type StakingMsg_Redelegate struct { + Amount Coin `json:"amount"` + DstValidator string `json:"dst_validator"` + SrcValidator string `json:"src_validator"` +} - This should be called "option" for consistency with Cosmos SDK. Sorry for that. See . - */ - Vote VoteOption `json:"vote"` - ProposalId int `json:"proposal_id"` +type CosmosMsg_for_Empty_Stargate struct { + TypeUrl string `json:"type_url"` + Value Binary `json:"value"` } -type BankMsg_Send struct { +type DistributionMsg_FundCommunityPool struct { + // The amount to spend Amount []Coin `json:"amount"` - ToAddress string `json:"to_address"` } -type Expiration_AtTime Timestamp +type CosmosMsg_for_Empty_Staking StakingMsg + +type BankQuery_AllDenomMetadata struct { + Pagination *PageRequest `json:"pagination,omitempty"` +} + +type Expiration_AtHeight int + +type WasmMsg_ClearAdmin struct { + ContractAddr string `json:"contract_addr"` +} + +type IbcQuery_PortId struct{} type WasmMsg_Instantiate struct { - // msg is the JSON-encoded InstantiateMsg struct (as raw Binary) - Msg Binary `json:"msg"` - Admin *string `json:"admin,omitempty"` CodeId int `json:"code_id"` Funds []Coin `json:"funds"` /* @@ -589,17 +734,69 @@ type WasmMsg_Instantiate struct { Valid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace */ Label string `json:"label"` + // msg is the JSON-encoded InstantiateMsg struct (as raw Binary) + Msg Binary `json:"msg"` + Admin *string `json:"admin,omitempty"` } +type QueryRequest_for_Empty_Staking StakingQuery -type StakingMsg_Redelegate struct { - Amount Coin `json:"amount"` - DstValidator string `json:"dst_validator"` - SrcValidator string `json:"src_validator"` +type GovMsg_VoteWeighted struct { + Options []WeightedVoteOption `json:"options"` + ProposalId int `json:"proposal_id"` +} +type CosmosMsg_for_Empty_Custom Empty + +type WasmQuery_ContractInfo struct { + ContractAddr string `json:"contract_addr"` } -type Expiration_Never struct{} +type BankQuery_Supply struct { + Denom string `json:"denom"` +} -type DistributionMsg_FundCommunityPool struct { - // The amount to spend +type StakingQuery_AllDelegations struct { + Delegator string `json:"delegator"` +} + +type BankQuery_AllBalances struct { + Address string `json:"address"` +} +type CosmosMsg_for_Empty_Wasm WasmMsg + +type IbcQuery_Channel struct { + ChannelId string `json:"channel_id"` + PortId *string `json:"port_id,omitempty"` +} + +type GovMsg_Vote struct { + ProposalId int `json:"proposal_id"` + /* + The vote option. + + This should be called "option" for consistency with Cosmos SDK. Sorry for that. See . + */ + Vote VoteOption `json:"vote"` +} + +type IbcQuery_ListChannels struct { + PortId *string `json:"port_id,omitempty"` +} +type QueryRequest_for_Empty_Ibc IbcQuery + +type StakingQuery_BondedDenom struct{} + +type WasmQuery_Raw struct { + // Key is the raw key used in the contracts Storage + Key Binary `json:"key"` + ContractAddr string `json:"contract_addr"` +} + +type StakingMsg_Delegate struct { + Amount Coin `json:"amount"` + Validator string `json:"validator"` +} + +type BankMsg_Send struct { Amount []Coin `json:"amount"` + ToAddress string `json:"to_address"` } diff --git a/e2e/interchaintestv8/types/cwicacontroller/query.go b/e2e/interchaintestv8/types/cwicacontroller/query.go index 020070bd..8346e587 100644 --- a/e2e/interchaintestv8/types/cwicacontroller/query.go +++ b/e2e/interchaintestv8/types/cwicacontroller/query.go @@ -13,12 +13,12 @@ import ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { - // GetChannel is the client API for the QueryMsg_GetChannel query message - GetChannel(ctx context.Context, req *QueryMsg_GetChannel, opts ...grpc.CallOption) (*State, error) // GetContractState is the client API for the QueryMsg_GetContractState query message - GetContractState(ctx context.Context, req *QueryMsg_GetContractState, opts ...grpc.CallOption) (*State_2, error) + GetContractState(ctx context.Context, req *QueryMsg_GetContractState, opts ...grpc.CallOption) (*State, error) // Ownership is the client API for the QueryMsg_Ownership query message Ownership(ctx context.Context, req *QueryMsg_Ownership, opts ...grpc.CallOption) (*Ownership_for_String, error) + // GetChannel is the client API for the QueryMsg_GetChannel query message + GetChannel(ctx context.Context, req *QueryMsg_GetChannel, opts ...grpc.CallOption) (*ChannelState, error) } type queryClient struct { @@ -65,8 +65,8 @@ func (q *queryClient) queryContract(ctx context.Context, rawQueryData []byte, op return out.Data, nil } -func (q *queryClient) GetChannel(ctx context.Context, req *QueryMsg_GetChannel, opts ...grpc.CallOption) (*State, error) { - rawQueryData, err := json.Marshal(&QueryMsg{GetChannel: req}) +func (q *queryClient) Ownership(ctx context.Context, req *QueryMsg_Ownership, opts ...grpc.CallOption) (*Ownership_for_String, error) { + rawQueryData, err := json.Marshal(&QueryMsg{Ownership: req}) if err != nil { return nil, err } @@ -76,7 +76,7 @@ func (q *queryClient) GetChannel(ctx context.Context, req *QueryMsg_GetChannel, return nil, err } - var response State + var response Ownership_for_String if err := json.Unmarshal(rawResponseData, &response); err != nil { return nil, err } @@ -84,8 +84,8 @@ func (q *queryClient) GetChannel(ctx context.Context, req *QueryMsg_GetChannel, return &response, nil } -func (q *queryClient) GetContractState(ctx context.Context, req *QueryMsg_GetContractState, opts ...grpc.CallOption) (*State_2, error) { - rawQueryData, err := json.Marshal(&QueryMsg{GetContractState: req}) +func (q *queryClient) GetChannel(ctx context.Context, req *QueryMsg_GetChannel, opts ...grpc.CallOption) (*ChannelState, error) { + rawQueryData, err := json.Marshal(&QueryMsg{GetChannel: req}) if err != nil { return nil, err } @@ -95,7 +95,7 @@ func (q *queryClient) GetContractState(ctx context.Context, req *QueryMsg_GetCon return nil, err } - var response State_2 + var response ChannelState if err := json.Unmarshal(rawResponseData, &response); err != nil { return nil, err } @@ -103,8 +103,8 @@ func (q *queryClient) GetContractState(ctx context.Context, req *QueryMsg_GetCon return &response, nil } -func (q *queryClient) Ownership(ctx context.Context, req *QueryMsg_Ownership, opts ...grpc.CallOption) (*Ownership_for_String, error) { - rawQueryData, err := json.Marshal(&QueryMsg{Ownership: req}) +func (q *queryClient) GetContractState(ctx context.Context, req *QueryMsg_GetContractState, opts ...grpc.CallOption) (*State, error) { + rawQueryData, err := json.Marshal(&QueryMsg{GetContractState: req}) if err != nil { return nil, err } @@ -114,7 +114,7 @@ func (q *queryClient) Ownership(ctx context.Context, req *QueryMsg_Ownership, op return nil, err } - var response Ownership_for_String + var response State if err := json.Unmarshal(rawResponseData, &response); err != nil { return nil, err } diff --git a/e2e/interchaintestv8/types/cwicaowner/msgs.go b/e2e/interchaintestv8/types/cwicaowner/msgs.go index 93c2d02e..05696a31 100644 --- a/e2e/interchaintestv8/types/cwicaowner/msgs.go +++ b/e2e/interchaintestv8/types/cwicaowner/msgs.go @@ -27,15 +27,8 @@ type QueryMsg struct { GetIcaCount *QueryMsg_GetIcaCount `json:"get_ica_count,omitempty"` } -// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. -type IbcOrder string - -const ( - IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" - IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" -) - type IbcPacket struct { + Timeout IbcTimeout `json:"timeout"` // The raw data sent from the other side in the packet Data Binary `json:"data"` // identifies the channel and port on the receiving chain. @@ -44,86 +37,51 @@ type IbcPacket struct { Sequence int `json:"sequence"` // identifies the channel and port on the sending chain. Src IbcEndpoint `json:"src"` - Timeout IbcTimeout `json:"timeout"` } -/* -A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq. - -# Examples - -Use `from` to create instances of this and `u64` to get the value out: - -``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42); - -let b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ``` -*/ -type Uint64 string - -type QueryMsg_GetContractState struct{} - -type ExecuteMsg_CreateIcaContract struct { - Salt *string `json:"salt,omitempty"` - ChannelOpenInitOptions ChannelOpenInitOptions `json:"channel_open_init_options"` -} -type ExecuteMsg_ReceiveIcaCallback IcaControllerCallbackMsg - -// IbcChannel defines all information on a channel. This is generally used in the hand-shake process, but can be queried directly. -type IbcChannel struct { - // Note: in ibcv3 this may be "", in the IbcOpenChannel handshake messages - Version string `json:"version"` - // The connection upon which this channel was created. If this is a multi-hop channel, we only expose the first hop. - ConnectionId string `json:"connection_id"` - CounterpartyEndpoint IbcEndpoint `json:"counterparty_endpoint"` - Endpoint IbcEndpoint `json:"endpoint"` - Order IbcOrder `json:"order"` -} - -type IbcEndpoint struct { - ChannelId string `json:"channel_id"` - PortId string `json:"port_id"` -} - -type QueryMsg_GetIcaContractState struct { - IcaId int `json:"ica_id"` +// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. +type IbcTimeout struct { + Timestamp *Timestamp `json:"timestamp,omitempty"` + Block *IbcTimeoutBlock `json:"block,omitempty"` } -type QueryMsg_GetIcaCount struct{} - // IcaState is the state of the ICA. type IcaState struct { - ChannelState State `json:"channel_state"` IcaAddr string `json:"ica_addr"` IcaId int `json:"ica_id"` TxEncoding TxEncoding `json:"tx_encoding"` + ChannelState ChannelState `json:"channel_state"` } +type ExecuteMsg_ReceiveIcaCallback IcaControllerCallbackMsg -// IcaContractState is the state of the cw-ica-controller contract. -type IcaContractState struct { - ContractAddr Addr `json:"contract_addr"` - IcaState *IcaState `json:"ica_state,omitempty"` -} - -// IcaControllerCallbackMsg is the type of message that this contract can send to other contracts. -type IcaControllerCallbackMsg struct { - // OnAcknowledgementPacketCallback is the callback that this contract makes to other contracts when it receives an acknowledgement packet. - OnAcknowledgementPacketCallback *IcaControllerCallbackMsg_OnAcknowledgementPacketCallback `json:"on_acknowledgement_packet_callback,omitempty"` - // OnTimeoutPacketCallback is the callback that this contract makes to other contracts when it receives a timeout packet. - OnTimeoutPacketCallback *IcaControllerCallbackMsg_OnTimeoutPacketCallback `json:"on_timeout_packet_callback,omitempty"` - // OnChannelOpenAckCallback is the callback that this contract makes to other contracts when it receives a channel open acknowledgement. - OnChannelOpenAckCallback *IcaControllerCallbackMsg_OnChannelOpenAckCallback `json:"on_channel_open_ack_callback,omitempty"` +// The options needed to initialize the IBC channel. +type ChannelOpenInitOptions struct { + // The counterparty connection id on the counterparty chain. + CounterpartyConnectionId string `json:"counterparty_connection_id"` + // The counterparty port id. If not specified, [`crate::ibc::types::keys::HOST_PORT_ID`] is used. Currently, this contract only supports the host port. + CounterpartyPortId *string `json:"counterparty_port_id,omitempty"` + // The order of the channel. If not specified, [`IbcOrder::Ordered`] is used. [`IbcOrder::Unordered`] is only supported if the counterparty chain is using `ibc-go` v8.1.0 or later. + ChannelOrdering *IbcOrder `json:"channel_ordering,omitempty"` + // The connection id on this chain. + ConnectionId string `json:"connection_id"` } -// `TxEncoding` is the encoding of the transactions sent to the ICA host. -type TxEncoding string +// IbcOrder defines if a channel is ORDERED or UNORDERED Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 Naming comes from the protobuf files and go translations. +type IbcOrder string const ( - // `Protobuf` is the protobuf serialization of the CosmosSDK's Any. - TxEncoding_Proto3 TxEncoding = "proto3" - // `Proto3Json` is the json serialization of the CosmosSDK's Any. - TxEncoding_Proto3Json TxEncoding = "proto3json" + IbcOrder_OrderUnordered IbcOrder = "ORDER_UNORDERED" + IbcOrder_OrderOrdered IbcOrder = "ORDER_ORDERED" ) +// State is the state of the IBC application's channel. This application only supports one channel. +type ChannelState struct { + // The IBC channel, as defined by cosmwasm. + Channel IbcChannel `json:"channel"` + // The status of the channel. + ChannelStatus ChannelStatus `json:"channel_status"` +} + // `Data` is the response to an ibc packet. It either contains a result or an error. type Data struct { // Result is the result of a successful transaction. @@ -132,30 +90,7 @@ type Data struct { Error *Data_Error `json:"error,omitempty"` } -/* -A point in time in nanosecond precision. - -This type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z. - -## Examples - -``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202); - -let ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ``` -*/ -type Timestamp Uint64 - -// The options needed to initialize the IBC channel. -type ChannelOpenInitOptions struct { - // The connection id on this chain. - ConnectionId string `json:"connection_id"` - // The counterparty connection id on the counterparty chain. - CounterpartyConnectionId string `json:"counterparty_connection_id"` - // The counterparty port id. If not specified, [`crate::ibc::types::keys::HOST_PORT_ID`] is used. Currently, this contract only supports the host port. - CounterpartyPortId *string `json:"counterparty_port_id,omitempty"` - // The order of the channel. If not specified, [`IbcOrder::Ordered`] is used. [`IbcOrder::Unordered`] is only supported if the counterparty chain is using `ibc-go` v8.1.0 or later. - ChannelOrdering *IbcOrder `json:"channel_ordering,omitempty"` -} +type QueryMsg_GetIcaCount struct{} // ContractState is the state of the IBC application. type ContractState struct { @@ -165,38 +100,43 @@ type ContractState struct { IcaControllerCodeId int `json:"ica_controller_code_id"` } +type QueryMsg_GetContractState struct{} + // Status is the status of an IBC channel. -type Status string +type ChannelStatus string const ( // Uninitialized is the default state of the channel. - Status_StateUninitializedUnspecified Status = "STATE_UNINITIALIZED_UNSPECIFIED" + ChannelStatus_StateUninitializedUnspecified ChannelStatus = "STATE_UNINITIALIZED_UNSPECIFIED" // Init is the state of the channel when it is created. - Status_StateInit Status = "STATE_INIT" + ChannelStatus_StateInit ChannelStatus = "STATE_INIT" // TryOpen is the state of the channel when it is trying to open. - Status_StateTryopen Status = "STATE_TRYOPEN" + ChannelStatus_StateTryopen ChannelStatus = "STATE_TRYOPEN" // Open is the state of the channel when it is open. - Status_StateOpen Status = "STATE_OPEN" + ChannelStatus_StateOpen ChannelStatus = "STATE_OPEN" // Closed is the state of the channel when it is closed. - Status_StateClosed Status = "STATE_CLOSED" + ChannelStatus_StateClosed ChannelStatus = "STATE_CLOSED" // The channel has just accepted the upgrade handshake attempt and is flushing in-flight packets. Added in `ibc-go` v8.1.0. - Status_StateFlushing Status = "STATE_FLUSHING" + ChannelStatus_StateFlushing ChannelStatus = "STATE_FLUSHING" // The channel has just completed flushing any in-flight packets. Added in `ibc-go` v8.1.0. - Status_StateFlushcomplete Status = "STATE_FLUSHCOMPLETE" + ChannelStatus_StateFlushcomplete ChannelStatus = "STATE_FLUSHCOMPLETE" ) -type ExecuteMsg_SendPredefinedAction struct { - // The ICA ID. - IcaId int `json:"ica_id"` - // The recipient's address, on the counterparty chain, to send the tokens to from ICA host. - ToAddress string `json:"to_address"` +type ExecuteMsg_CreateIcaContract struct { + ChannelOpenInitOptions ChannelOpenInitOptions `json:"channel_open_init_options"` + Salt *string `json:"salt,omitempty"` } -// In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set. -type IbcTimeout struct { - Block *IbcTimeoutBlock `json:"block,omitempty"` - Timestamp *Timestamp `json:"timestamp,omitempty"` -} +/* +A human readable address. + +In Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length. + +This type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances. + +This type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance. +*/ +type Addr string /* Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline. @@ -205,16 +145,39 @@ This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec execute::send_cosmos_msgs(deps, env, info, messages, packet_memo, timeout_seconds), + } => execute::send_cosmos_msgs( + deps, + env, + info, + messages, + queries, + packet_memo, + timeout_seconds, + ), ExecuteMsg::UpdateOwnership(action) => execute::update_ownership(deps, env, info, action), } } +/// Handles the replies to the submessages. +#[entry_point] +#[allow(clippy::pedantic)] +pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { + match msg.id { + keys::reply_ids::SEND_QUERY_PACKET => reply::send_query_packet(deps, env, msg.result), + _ => Err(ContractError::UnknownReplyId(msg.id)), + } +} + /// Handles the query of the contract. #[entry_point] #[allow(clippy::pedantic)] @@ -99,15 +118,17 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result, + queries: Vec>, packet_memo: Option, timeout_seconds: Option, ) -> Result { @@ -179,16 +201,25 @@ mod execute { let contract_state = state::STATE.load(deps.storage)?; let ica_info = contract_state.get_ica_info()?; + let has_queries = !queries.is_empty(); let ica_packet = IcaPacketData::from_cosmos_msgs( + deps.storage, messages, + queries, &ica_info.encoding, packet_memo, &ica_info.ica_address, )?; let send_packet_msg = ica_packet.to_ibc_msg(&env, ica_info.channel_id, timeout_seconds)?; - Ok(Response::default().add_message(send_packet_msg)) + let send_packet_submsg = if has_queries { + SubMsg::reply_on_success(send_packet_msg, keys::reply_ids::SEND_QUERY_PACKET) + } else { + SubMsg::new(send_packet_msg) + }; + + Ok(Response::default().add_submessage(send_packet_submsg)) } /// Update the ownership of the contract. @@ -229,6 +260,36 @@ mod execute { } } +mod reply { + use cosmwasm_std::SubMsgResult; + + use super::{state, ContractError, DepsMut, Env, Response}; + + /// Handles the reply to the query packet. + #[allow(clippy::needless_pass_by_value)] + pub fn send_query_packet( + deps: DepsMut, + _env: Env, + result: SubMsgResult, + ) -> Result { + match result { + SubMsgResult::Ok(resp) => { + let sequence = anybuf::Bufany::deserialize(&resp.data.unwrap_or_default())? + .uint64(1) + .unwrap(); + let channel_id = state::STATE.load(deps.storage)?.get_ica_info()?.channel_id; + let query_paths = state::QUERY.load(deps.storage)?; + + state::QUERY.remove(deps.storage); + state::PENDING_QUERIES.save(deps.storage, (&channel_id, sequence), &query_paths)?; + + Ok(Response::default()) + } + SubMsgResult::Err(err) => unreachable!("query packet failed: {err}"), + } + } +} + mod query { use super::{state, ChannelState, ContractState, Deps, StdResult}; diff --git a/src/ibc/relay.rs b/src/ibc/relay.rs index e540b8f1..3e002ae2 100644 --- a/src/ibc/relay.rs +++ b/src/ibc/relay.rs @@ -9,7 +9,7 @@ use cosmwasm_std::{ IbcPacketTimeoutMsg, IbcReceiveResponse, Never, }; -use crate::types::{state, ContractError}; +use crate::types::{query_msg, state, ContractError}; use super::types::{events, packet::acknowledgement::Data as AcknowledgementData}; @@ -84,7 +84,9 @@ mod ibc_packet_ack { use crate::types::callbacks::IcaControllerCallbackMsg; - use super::{events, state, AcknowledgementData, ContractError, DepsMut, IbcBasicResponse}; + use super::{ + events, query_msg, state, AcknowledgementData, ContractError, DepsMut, IbcBasicResponse, + }; /// Handles the successful acknowledgement of an ica packet. This means that the /// transaction was successfully executed on the host chain. @@ -95,15 +97,27 @@ mod ibc_packet_ack { relayer: Addr, res: Binary, ) -> Result { - let state = state::STATE.load(deps.storage)?; - let success_event = events::packet_ack::success(&packet, &res); - - if let Some(contract_addr) = state.callback_address { + let ica_acknowledgement = AcknowledgementData::Result(res); + let query_result = state::PENDING_QUERIES + .may_load(deps.storage, (&packet.src.channel_id, packet.sequence))? + .map( + |paths| -> Result { + let resp_msg = + ica_acknowledgement.decode_module_query_safe_resp_last_index()?; + Ok(query_msg::result_from_response(paths, &resp_msg)) + }, + ) + .transpose()?; + + state::PENDING_QUERIES.remove(deps.storage, (&packet.src.channel_id, packet.sequence)); + + if let Some(contract_addr) = state::STATE.load(deps.storage)?.callback_address { let callback_msg = IcaControllerCallbackMsg::OnAcknowledgementPacketCallback { - ica_acknowledgement: AcknowledgementData::Result(res), + ica_acknowledgement, original_packet: packet, relayer, + query_result, } .into_cosmos_msg(contract_addr)?; @@ -125,14 +139,14 @@ mod ibc_packet_ack { err: String, ) -> Result { let state = state::STATE.load(deps.storage)?; - let error_event = events::packet_ack::error(&packet, &err); if let Some(contract_addr) = state.callback_address { let callback_msg = IcaControllerCallbackMsg::OnAcknowledgementPacketCallback { - ica_acknowledgement: AcknowledgementData::Error(err), + ica_acknowledgement: AcknowledgementData::Error(err.clone()), original_packet: packet, relayer, + query_result: Some(query_msg::IcaQueryResult::Error(err)), } .into_cosmos_msg(contract_addr)?; @@ -148,7 +162,7 @@ mod ibc_packet_ack { mod ibc_packet_timeout { use cosmwasm_std::{Addr, IbcPacket}; - use crate::types::{callbacks::IcaControllerCallbackMsg, state::STATE}; + use crate::types::{callbacks::IcaControllerCallbackMsg, state}; use super::{ContractError, DepsMut, IbcBasicResponse}; @@ -159,7 +173,9 @@ mod ibc_packet_timeout { packet: IbcPacket, relayer: Addr, ) -> Result { - let state = STATE.load(deps.storage)?; + let state = state::STATE.load(deps.storage)?; + + state::PENDING_QUERIES.remove(deps.storage, (&packet.src.channel_id, packet.sequence)); if let Some(contract_addr) = state.callback_address { let callback_msg = IcaControllerCallbackMsg::OnTimeoutPacketCallback { diff --git a/src/ibc/types/packet.rs b/src/ibc/types/packet.rs index 88d5ea82..0cf7b04e 100644 --- a/src/ibc/types/packet.rs +++ b/src/ibc/types/packet.rs @@ -75,6 +75,76 @@ impl IcaPacketData { /// Panics if the [`CosmosMsg`] is not supported. /// /// The supported [`CosmosMsg`]s for [`TxEncoding::Protobuf`] are listed in [`convert_to_proto_any`]. + #[cfg(feature = "query")] + pub fn from_cosmos_msgs( + #[cfg(feature = "export")] storage: &mut dyn cosmwasm_std::Storage, + messages: Vec, + queries: Vec>, + encoding: &TxEncoding, + memo: Option, + ica_address: &str, + ) -> StdResult { + match encoding { + TxEncoding::Protobuf => { + use crate::types::query_msg; + + let mut proto_anys = messages + .into_iter() + .map(|msg| -> StdResult { + convert_to_proto_any(msg, ica_address.to_string()) + .map_err(|e| StdError::generic_err(e.to_string())) + }) + .collect::>>()?; + + if !queries.is_empty() { + let (abci_queries, _paths): ( + Vec, + Vec<(String, bool)>, + ) = queries.into_iter().fold((vec![], vec![]), |mut acc, msg| { + let (path, data, is_stargate) = query_msg::query_to_protobuf(msg); + + acc.1.push((path.clone(), is_stargate)); + acc.0 + .push(query_msg::proto::AbciQueryRequest { path, data }); + + acc + }); + + #[cfg(feature = "export")] + #[allow(clippy::used_underscore_binding)] + crate::types::state::QUERY.save(storage, &_paths)?; + + let query_msg = query_msg::proto::MsgModuleQuerySafe { + signer: ica_address.to_string(), + requests: abci_queries, + }; + + proto_anys.push(cosmos_sdk_proto::Any::from_msg(&query_msg).map_err(|e| { + StdError::generic_err(format!("failed to convert query msg: {e}")) + })?); + } + + Ok(Self::from_proto_anys(proto_anys, memo)) + } + TxEncoding::Proto3Json => StdResult::Err(StdError::generic_err( + "unsupported encoding: proto3json".to_string(), + )), + } + } + + /// Creates a new [`IcaPacketData`] from a list of [`CosmosMsg`] messages + /// + /// # Errors + /// + /// Returns an error if the [`CosmosMsg`] cannot be serialized to [`cosmos_sdk_proto::Any`] + /// when using the [`TxEncoding::Protobuf`] encoding. + /// + /// # Panics + /// + /// Panics if the [`CosmosMsg`] is not supported. + /// + /// The supported [`CosmosMsg`]s for [`TxEncoding::Protobuf`] are listed in [`convert_to_proto_any`]. + #[cfg(not(feature = "query"))] pub fn from_cosmos_msgs( messages: Vec, encoding: &TxEncoding, @@ -90,6 +160,7 @@ impl IcaPacketData { .map_err(|e| StdError::generic_err(e.to_string())) }) .collect::>>()?; + Ok(Self::from_proto_anys(proto_anys, memo)) } TxEncoding::Proto3Json => StdResult::Err(StdError::generic_err( @@ -125,7 +196,15 @@ impl IcaPacketData { pub mod acknowledgement { use cosmwasm_std::Binary; - use super::cw_serde; + use cosmos_sdk_proto::cosmos::base::abci::v1beta1::TxMsgData; + use cosmos_sdk_proto::prost::Message; + + use crate::types::ContractError; + + #[cfg(feature = "query")] + use crate::types::query_msg; + + use super::{cw_serde, StdError}; /// `Data` is the response to an ibc packet. It either contains a result or an error. #[cw_serde] @@ -136,6 +215,57 @@ pub mod acknowledgement { /// It is a string of the error message (not base64 encoded). Error(String), } + + impl Data { + /// `to_tx_msg_data` converts the acknowledgement to a [`TxMsgData`]. + /// + /// # Errors + /// Returns an error if the acknowledgement is an error or if the data cannot be decoded. + pub fn to_tx_msg_data(&self) -> Result { + match self { + Self::Result(data) => Ok(TxMsgData::decode(data.as_slice())?), + Self::Error(err) => Err(StdError::generic_err(err))?, + } + } + + /// `decode_module_query_safe_resp` decodes the acknowledgement at the given index to a [`query_msg::proto::MsgModuleQuerySafeResponse`]. + /// + /// # Errors + /// Returns an error if the acknowledgement is an error or if the data at the index cannot be decoded. + #[cfg(feature = "query")] + pub fn decode_module_query_safe_resp( + &self, + index: usize, + ) -> Result { + let tx_msg_data = self.to_tx_msg_data()?; + let msg_resp = tx_msg_data.msg_responses.get(index).ok_or_else(|| { + StdError::generic_err("no MsgData found at the given index".to_string()) + })?; + + Ok(query_msg::proto::MsgModuleQuerySafeResponse::decode( + msg_resp.value.as_slice(), + )?) + } + + /// `decode_module_query_safe_resp` decodes the acknowledgement at the last index to a [`query_msg::proto::MsgModuleQuerySafeResponse`]. + /// This is a convenience function since the contract only sends one query at the last index. + /// + /// # Errors + /// Returns an error if the acknowledgement is an error or if the data at the index cannot be decoded. + #[cfg(feature = "export")] + pub fn decode_module_query_safe_resp_last_index( + &self, + ) -> Result { + let tx_msg_data = self.to_tx_msg_data()?; + let msg_resp = tx_msg_data.msg_responses.last().ok_or_else(|| { + StdError::generic_err("no MsgData found at the given index".to_string()) + })?; + + Ok(query_msg::proto::MsgModuleQuerySafeResponse::decode( + msg_resp.value.as_slice(), + )?) + } + } } #[cfg(test)] diff --git a/src/types/callbacks.rs b/src/types/callbacks.rs index 2029a64e..8f5978c6 100644 --- a/src/types/callbacks.rs +++ b/src/types/callbacks.rs @@ -12,10 +12,19 @@ use crate::ibc::types::{ metadata::TxEncoding, packet::acknowledgement::Data as AcknowledgementData, }; -/// IcaControllerCallbackMsg is the type of message that this contract can send to other contracts. -#[cw_serde] +/// `IcaControllerCallbackMsg` is the type of message that this contract can send to other contracts. +#[derive( + ::cosmwasm_schema::serde::Serialize, + ::cosmwasm_schema::serde::Deserialize, + ::std::clone::Clone, + ::std::fmt::Debug, + ::std::cmp::PartialEq, + ::cosmwasm_schema::schemars::JsonSchema, +)] +#[serde(rename_all = "snake_case", crate = "::cosmwasm_schema::serde")] +#[schemars(crate = "::cosmwasm_schema::schemars")] pub enum IcaControllerCallbackMsg { - /// OnAcknowledgementPacketCallback is the callback that this contract makes to other contracts + /// `OnAcknowledgementPacketCallback` is the callback that this contract makes to other contracts /// when it receives an acknowledgement packet. OnAcknowledgementPacketCallback { /// The deserialized ICA acknowledgement data @@ -24,8 +33,12 @@ pub enum IcaControllerCallbackMsg { original_packet: IbcPacket, /// The relayer that submitted acknowledgement packet relayer: Addr, + /// The responses to the queries. + #[cfg(feature = "query")] + #[serde(skip_serializing_if = "Option::is_none")] + query_result: Option, }, - /// OnTimeoutPacketCallback is the callback that this contract makes to other contracts + /// `OnTimeoutPacketCallback` is the callback that this contract makes to other contracts /// when it receives a timeout packet. OnTimeoutPacketCallback { /// The original packet that was sent @@ -33,7 +46,7 @@ pub enum IcaControllerCallbackMsg { /// The relayer that submitted acknowledgement packet relayer: Addr, }, - /// OnChannelOpenAckCallback is the callback that this contract makes to other contracts + /// `OnChannelOpenAckCallback` is the callback that this contract makes to other contracts /// when it receives a channel open acknowledgement. OnChannelOpenAckCallback { /// The channel that was opened. diff --git a/src/types/cosmos_msg.rs b/src/types/cosmos_msg.rs index eb4c7583..cdbf260e 100644 --- a/src/types/cosmos_msg.rs +++ b/src/types/cosmos_msg.rs @@ -44,7 +44,7 @@ pub fn convert_to_proto_any(msg: CosmosMsg, from_address: String) -> Result convert_to_any::bank(bank_msg, from_address), CosmosMsg::Ibc(ibc_msg) => convert_to_any::ibc(ibc_msg, from_address), CosmosMsg::Wasm(wasm_msg) => convert_to_any::wasm(wasm_msg, from_address), - CosmosMsg::Gov(gov_msg) => Ok(convert_to_any::gov(gov_msg, from_address)), + CosmosMsg::Gov(gov_msg) => convert_to_any::gov(gov_msg, from_address), #[cfg(feature = "staking")] CosmosMsg::Staking(staking_msg) => convert_to_any::staking(staking_msg, from_address), #[cfg(feature = "staking")] @@ -69,7 +69,6 @@ mod convert_to_any { }, ibc::{applications::transfer::v1::MsgTransfer, core::client::v1::Height}, prost::EncodeError, - traits::Message, Any, }; @@ -187,35 +186,27 @@ mod convert_to_any { msg, funds, salt, - } => { - let proto_msg = MsgInstantiateContract2 { - sender, - admin: admin.unwrap_or_default(), - code_id, - label, - msg: msg.to_vec(), - funds: funds - .into_iter() - .map(|coin| ProtoCoin { - denom: coin.denom, - amount: coin.amount.to_string(), - }) - .collect(), - salt: salt.to_vec(), - fix_msg: false, - }; - - // TODO: use Any::from_msg after cosmos-sdk-proto > 0.20.0 - Ok(Any { - type_url: "/cosmwasm.wasm.v1.MsgInstantiateContract2".to_string(), - value: proto_msg.encode_to_vec(), - }) - } + } => Any::from_msg(&MsgInstantiateContract2 { + sender, + admin: admin.unwrap_or_default(), + code_id, + label, + msg: msg.to_vec(), + funds: funds + .into_iter() + .map(|coin| ProtoCoin { + denom: coin.denom, + amount: coin.amount.to_string(), + }) + .collect(), + salt: salt.to_vec(), + fix_msg: false, + }), _ => panic!("Unsupported WasmMsg"), } } - pub fn gov(msg: GovMsg, voter: String) -> Any { + pub fn gov(msg: GovMsg, voter: String) -> Result { const fn convert_to_proto_vote_option(option: &VoteOption) -> ProtoVoteOption { match option { VoteOption::Yes => ProtoVoteOption::Yes, @@ -226,19 +217,11 @@ mod convert_to_any { } match msg { - GovMsg::Vote { proposal_id, vote } => { - let value = MsgVote { - voter, - proposal_id, - option: convert_to_proto_vote_option(&vote) as i32, - }; - - // TODO: use Any::from_msg when cosmos-sdk-proto is > 0.20.0 - Any { - type_url: "/cosmos.gov.v1beta1.MsgVote".to_string(), - value: value.encode_to_vec(), - } - } + GovMsg::Vote { proposal_id, vote } => Any::from_msg(&MsgVote { + voter, + proposal_id, + option: convert_to_proto_vote_option(&vote) as i32, + }), GovMsg::VoteWeighted { proposal_id, options, @@ -253,17 +236,12 @@ mod convert_to_any { }) .collect(); - let value = MsgVoteWeighted { + Any::from_msg(&MsgVoteWeighted { proposal_id, voter, options, metadata: String::new(), - }; - - Any { - type_url: "/cosmos.gov.v1.MsgVoteWeighted".to_string(), - value: value.encode_to_vec(), - } + }) } } } diff --git a/src/types/error.rs b/src/types/error.rs index 535a301d..4d7fccae 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -1,20 +1,18 @@ //! This module defines [`ContractError`]. -use std::string::FromUtf8Error; - -use cosmwasm_std::StdError; use thiserror::Error; /// `ContractError` is the error type returned by contract's functions. #[allow(missing_docs)] #[allow(clippy::module_name_repetitions)] +#[non_exhaustive] #[derive(Error, Debug)] pub enum ContractError { #[error("{0}")] - Std(#[from] StdError), + Std(#[from] cosmwasm_std::StdError), #[error("FromUtf8Error: {0}")] - JsonSerde(#[from] FromUtf8Error), + JsonSerde(#[from] std::string::FromUtf8Error), #[error("json_serde_wasm serialization error: {0}")] JsonWasmSerialize(#[from] serde_json_wasm::ser::Error), @@ -25,12 +23,18 @@ pub enum ContractError { #[error("prost encoding error: {0}")] ProstEncodeError(#[from] cosmos_sdk_proto::prost::EncodeError), + #[error("prost decoding error: {0}")] + ProstDecodeError(#[from] cosmos_sdk_proto::prost::DecodeError), + #[error("semver parse error: {0}")] SemverError(#[from] semver::Error), #[error("{0}")] OwnershipError(#[from] cw_ownable::OwnershipError), + #[error("{0}")] + BufanyError(#[from] anybuf::BufanyError), + #[error("this contract must have an owner")] OwnershipCannotBeRenounced, @@ -88,6 +92,15 @@ pub enum ContractError { #[error("invalid channel status: expected {expected}, got {actual}")] InvalidChannelStatus { expected: String, actual: String }, + #[error("no callback address is set for the contract")] + NoCallbackAddress, + #[error("unsupported packet encoding: {0}")] UnsupportedPacketEncoding(String), + + #[error("empty response: {0}")] + EmptyResponse(String), + + #[error("unknown reply id: {0}")] + UnknownReplyId(u64), } diff --git a/src/types/keys.rs b/src/types/keys.rs index 7a609f59..2e340567 100644 --- a/src/types/keys.rs +++ b/src/types/keys.rs @@ -7,3 +7,11 @@ pub const CONTRACT_NAME: &str = "crates.io:cw-ica-controller"; /// `CONTRACT_VERSION` is the version of the cargo package. /// This is also the version of the contract recorded in [`cw2`] pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// This module contains [`cosmwasm_std::SubMsg`] reply ids. +pub mod reply_ids { + /// `SEND_QUERY_PACKET` is the reply id for a packet sent using + /// [`crate::types::msg::ExecuteMsg::SendQueryMsgs`] + #[cfg(feature = "query")] + pub const SEND_QUERY_PACKET: u64 = 1; +} diff --git a/src/types/mod.rs b/src/types/mod.rs index d9f47a50..7143a6b2 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -6,6 +6,8 @@ mod error; pub mod keys; #[allow(clippy::module_name_repetitions)] pub mod msg; +#[cfg(feature = "query")] +pub mod query_msg; pub mod state; pub use error::ContractError; diff --git a/src/types/msg.rs b/src/types/msg.rs index b6754b75..58c4ff04 100644 --- a/src/types/msg.rs +++ b/src/types/msg.rs @@ -22,6 +22,8 @@ pub struct InstantiateMsg { /// The messages to execute the ICA controller contract. #[cw_ownable::cw_ownable_execute] +#[serde_with::serde_as] +#[non_exhaustive] #[cw_serde] pub enum ExecuteMsg { /// `CreateChannel` makes the contract submit a stargate MsgChannelOpenInit to the chain. @@ -43,7 +45,15 @@ pub enum ExecuteMsg { /// **This is the recommended way to send messages to the ICA host.** SendCosmosMsgs { /// The stargate messages to convert and send to the ICA host. + #[serde_as(deserialize_as = "serde_with::DefaultOnNull")] messages: Vec, + /// The stargate queries to convert and send to the ICA host. + /// The queries are executed after the messages. + #[cfg(feature = "query")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + #[serde_as(deserialize_as = "serde_with::DefaultOnNull")] + queries: Vec>, /// Optional memo to include in the ibc packet. #[serde(skip_serializing_if = "Option::is_none")] packet_memo: Option, @@ -62,6 +72,7 @@ pub enum ExecuteMsg { /// The messages to query the ICA controller contract. #[cw_ownable::cw_ownable_query] +#[non_exhaustive] #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { diff --git a/src/types/query_msg.rs b/src/types/query_msg.rs new file mode 100644 index 00000000..12d7f1b9 --- /dev/null +++ b/src/types/query_msg.rs @@ -0,0 +1,585 @@ +//! This module contains the helpers to convert [`QueryRequest`] to protobuf bytes and vice versa. + +use cosmwasm_std::{Empty, QueryRequest}; + +pub use response::*; + +/// Converts a [`QueryRequest`] to a grpc method path, protobuf bytes, and a flag indicating if the query is stargate. +/// +/// # Panics +/// +/// Panics if the query type is not supported. +#[must_use] +pub fn query_to_protobuf(query: QueryRequest) -> (String, Vec, bool) { + match query { + QueryRequest::Bank(bank_query) => convert_to_protobuf::bank(bank_query), + QueryRequest::Stargate { path, data } => (path, data.0, true), + QueryRequest::Wasm(_) => panic!("wasmd queries are not marked module safe (yet)"), + QueryRequest::Ibc(_) => panic!("ibc-go queries are not marked module safe (yet)"), + QueryRequest::Custom(_) => panic!("custom queries are not supported"), + #[cfg(feature = "staking")] + QueryRequest::Staking(staking_query) => convert_to_protobuf::staking(staking_query), + #[cfg(feature = "staking")] + QueryRequest::Distribution(_) => { + panic!("distribution queries are not marked module safe (yet)") + } + _ => panic!("Unsupported QueryRequest"), + } +} + +/// Converts [`proto::MsgModuleQuerySafeResponse`] to [`IcaQueryResult`] using the storage. +#[cfg(feature = "export")] +#[must_use] +pub fn result_from_response( + paths: Vec<(String, bool)>, + resp_msg: &proto::MsgModuleQuerySafeResponse, +) -> IcaQueryResult { + if paths.len() != resp_msg.responses.len() { + return IcaQueryResult::Error(format!( + "expected {} responses, got {}", + paths.len(), + resp_msg.responses.len() + )); + } + + paths + .into_iter() + .zip(resp_msg.responses.iter()) + .map(|((path, is_stargate), resp)| from_protobuf::response(&path, resp, is_stargate)) + .collect::>() + .map_or_else( + |e| IcaQueryResult::Error(e.to_string()), + |responses| IcaQueryResult::Success { + height: resp_msg.height, + responses, + }, + ) +} + +/// The constants for the `query_msg` module. +pub mod constants { + /// The query path for the Balance query. + pub const BALANCE: &str = "/cosmos.bank.v1beta1.Query/Balance"; + /// The query path for the `AllBalances` query. + pub const ALL_BALANCES: &str = "/cosmos.bank.v1beta1.Query/AllBalances"; + /// The query path for the `DenomMetadata` query. + pub const DENOM_METADATA: &str = "/cosmos.bank.v1beta1.Query/DenomMetadata"; + /// The query path for the `AllDenomMetadata` query. + pub const ALL_DENOM_METADATA: &str = "/cosmos.bank.v1beta1.Query/DenomsMetadata"; + /// The query path for the Supply query. + pub const SUPPLY: &str = "/cosmos.bank.v1beta1.Query/SupplyOf"; + + /// The query path for the Validator query. + #[cfg(feature = "staking")] + pub const VALIDATOR: &str = "/cosmos.staking.v1beta1.Query/Validator"; + /// The query path for the `AllValidators` query. + #[cfg(feature = "staking")] + pub const ALL_VALIDATORS: &str = "/cosmos.staking.v1beta1.Query/Validators"; + /// The query path for the Delegation query. + #[cfg(feature = "staking")] + pub const DELEGATION: &str = "/cosmos.staking.v1beta1.Query/Delegation"; + /// The query path for the `AllDelegations` query. + #[cfg(feature = "staking")] + pub const ALL_DELEGATIONS: &str = "/cosmos.staking.v1beta1.Query/DelegatorDelegations"; + /// The query path for the `BondedDenom` query. + #[cfg(feature = "staking")] + pub const STAKING_PARAMS: &str = "/cosmos.staking.v1beta1.Query/Params"; +} + +#[allow(clippy::module_name_repetitions)] +mod response { + use cosmwasm_schema::cw_serde; + + /// The result of an ICA query packet. + #[cw_serde] + pub enum IcaQueryResult { + /// The query was successful and the responses are included. + Success { + /// The height of the block at which the queries were executed on the counterparty chain. + height: u64, + /// The responses to the queries. + responses: Vec, + }, + /// The query failed with an error message. The error string + /// often does not contain useful information for the end user. + Error(String), + } + + /// The response for a successful ICA query. + #[cw_serde] + pub enum IcaQueryResponse { + /// Response for a [`cosmwasm_std::BankQuery`]. + Bank(BankQueryResponse), + /// Response for a [`cosmwasm_std::QueryRequest::Stargate`]. + /// Protobuf encoded bytes stored as [`cosmwasm_std::Binary`]. + Stargate { + /// The response bytes. + data: cosmwasm_std::Binary, + /// The query grpc method + path: String, + }, + /// Response for a [`cosmwasm_std::StakingQuery`]. + #[cfg(feature = "staking")] + Staking(StakingQueryResponse), + } + + /// The response type for the [`cosmwasm_std::BankQuery`] queries. + #[cw_serde] + pub enum BankQueryResponse { + /// Response for the [`cosmwasm_std::BankQuery::Supply`] query. + Supply(cosmwasm_std::SupplyResponse), + /// Response for the [`cosmwasm_std::BankQuery::Balance`] query. + Balance(cosmwasm_std::BalanceResponse), + /// Response for the [`cosmwasm_std::BankQuery::AllBalances`] query. + AllBalances(cosmwasm_std::AllBalanceResponse), + /// Response for the [`cosmwasm_std::BankQuery::DenomMetadata`] query. + DenomMetadata(cosmwasm_std::DenomMetadataResponse), + /// Response for the [`cosmwasm_std::BankQuery::AllDenomMetadata`] query. + AllDenomMetadata(cosmwasm_std::AllDenomMetadataResponse), + } + + /// The response type for the [`cosmwasm_std::StakingQuery`] queries. + #[cfg(feature = "staking")] + #[cw_serde] + pub enum StakingQueryResponse { + /// Response for the [`cosmwasm_std::StakingQuery::BondedDenom`] query. + BondedDenom(cosmwasm_std::BondedDenomResponse), + /// Response for the [`cosmwasm_std::StakingQuery::AllDelegations`] query. + AllDelegations(IcaAllDelegationsResponse), + /// Response for the [`cosmwasm_std::StakingQuery::Delegation`] query. + Delegation(IcaDelegationResponse), + /// Response for the [`cosmwasm_std::StakingQuery::AllValidators`] query. + AllValidators(cosmwasm_std::AllValidatorsResponse), + /// Response for the [`cosmwasm_std::StakingQuery::Validator`] query. + Validator(cosmwasm_std::ValidatorResponse), + } + + /// Response for the [`cosmwasm_std::StakingQuery::Delegation`] query over ICA. + #[cfg(feature = "staking")] + #[cw_serde] + pub struct IcaDelegationResponse { + /// The delegation response if it exists. + pub delegation: Option, + } + + /// Response for the [`cosmwasm_std::StakingQuery::AllDelegations`] query over ICA. + #[cfg(feature = "staking")] + #[cw_serde] + pub struct IcaAllDelegationsResponse { + /// The delegations. + pub delegations: Vec, + } + + /// Delegation is the detailed information about a delegation. + #[cfg(feature = "staking")] + #[cw_serde] + pub struct Delegation { + /// The delegator address. + pub delegator: String, + /// A validator address (e.g. cosmosvaloper1...) + pub validator: String, + /// Delegation amount. + pub amount: cosmwasm_std::Coin, + } +} + +mod convert_to_protobuf { + use cosmos_sdk_proto::{ + cosmos::bank::v1beta1::{ + QueryAllBalancesRequest, QueryBalanceRequest, QueryDenomMetadataRequest, + QueryDenomsMetadataRequest, + }, + cosmos::{bank::v1beta1::QuerySupplyOfRequest, base::query::v1beta1::PageRequest}, + prost::Message, + }; + + use cosmwasm_std::BankQuery; + + use super::constants; + + pub fn bank(bank_query: BankQuery) -> (String, Vec, bool) { + match bank_query { + BankQuery::Balance { address, denom } => ( + constants::BALANCE.to_string(), + QueryBalanceRequest { address, denom }.encode_to_vec(), + false, + ), + BankQuery::AllBalances { address } => ( + constants::ALL_BALANCES.to_string(), + QueryAllBalancesRequest { + address, + pagination: None, + } + .encode_to_vec(), + false, + ), + BankQuery::DenomMetadata { denom } => ( + constants::DENOM_METADATA.to_string(), + QueryDenomMetadataRequest { denom }.encode_to_vec(), + false, + ), + BankQuery::AllDenomMetadata { pagination } => { + let pagination = pagination.map(|pagination| PageRequest { + key: pagination.key.unwrap_or_default().0, + limit: u64::from(pagination.limit), + reverse: pagination.reverse, + offset: 0, + count_total: false, + }); + + ( + constants::ALL_DENOM_METADATA.to_string(), + QueryDenomsMetadataRequest { pagination }.encode_to_vec(), + false, + ) + } + BankQuery::Supply { denom } => ( + constants::SUPPLY.to_string(), + QuerySupplyOfRequest { denom }.encode_to_vec(), + false, + ), + _ => panic!("Unsupported BankQuery"), + } + } + + #[cfg(feature = "staking")] + pub fn staking(staking_query: cosmwasm_std::StakingQuery) -> (String, Vec, bool) { + use cosmos_sdk_proto::cosmos::staking::v1beta1::{ + QueryDelegationRequest, QueryDelegatorDelegationsRequest, QueryParamsRequest, + QueryValidatorRequest, QueryValidatorsRequest, + }; + + match staking_query { + cosmwasm_std::StakingQuery::Validator { address } => ( + constants::VALIDATOR.to_string(), + QueryValidatorRequest { + validator_addr: address, + } + .encode_to_vec(), + false, + ), + cosmwasm_std::StakingQuery::AllValidators {} => ( + constants::ALL_VALIDATORS.to_string(), + QueryValidatorsRequest { + status: String::default(), + pagination: None, + } + .encode_to_vec(), + false, + ), + cosmwasm_std::StakingQuery::Delegation { + delegator, + validator, + } => ( + constants::DELEGATION.to_string(), + QueryDelegationRequest { + delegator_addr: delegator, + validator_addr: validator, + } + .encode_to_vec(), + false, + ), + cosmwasm_std::StakingQuery::AllDelegations { delegator } => ( + constants::ALL_DELEGATIONS.to_string(), + QueryDelegatorDelegationsRequest { + delegator_addr: delegator, + pagination: None, + } + .encode_to_vec(), + false, + ), + cosmwasm_std::StakingQuery::BondedDenom {} => ( + constants::STAKING_PARAMS.to_string(), + QueryParamsRequest::default().encode_to_vec(), + false, + ), + _ => panic!("Unsupported StakingQuery"), + } + } +} + +/// Converts the response bytes to a [`IcaQueryResponse`] using the query path. +pub mod from_protobuf { + use std::str::FromStr; + + use super::{constants, BankQueryResponse, IcaQueryResponse}; + + use crate::types::ContractError; + + use cosmos_sdk_proto::{ + cosmos::{ + bank::v1beta1::{ + Metadata as ProtoMetadata, QueryAllBalancesResponse, QueryBalanceResponse, + QueryDenomMetadataResponse, QueryDenomsMetadataResponse, QuerySupplyOfResponse, + }, + base::v1beta1::Coin as ProtoCoin, + }, + prost::Message, + }; + use cosmwasm_std::{ + AllBalanceResponse, AllDenomMetadataResponse, BalanceResponse, Binary, Coin, DenomMetadata, + DenomMetadataResponse, DenomUnit, StdResult, SupplyResponse, Uint128, + }; + + fn convert_to_coin(coin: ProtoCoin) -> StdResult { + Ok(Coin { + denom: coin.denom, + amount: Uint128::from_str(&coin.amount)?, + }) + } + + fn convert_to_metadata(metadata: ProtoMetadata) -> DenomMetadata { + DenomMetadata { + name: metadata.name, + symbol: metadata.symbol, + description: metadata.description, + base: metadata.base, + display: metadata.display, + uri: metadata.uri, + uri_hash: metadata.uri_hash, + denom_units: metadata + .denom_units + .into_iter() + .map(|unit| DenomUnit { + denom: unit.denom, + exponent: unit.exponent, + aliases: unit.aliases, + }) + .collect(), + } + } + + #[cfg(feature = "staking")] + fn convert_to_validator( + validator: cosmos_sdk_proto::cosmos::staking::v1beta1::Validator, + ) -> StdResult { + use cosmwasm_std::Decimal; + + let commission_rates = validator + .commission + .unwrap_or_default() + .commission_rates + .unwrap_or_default(); + + Ok(cosmwasm_std::Validator { + address: validator.operator_address, + commission: Decimal::from_str(&commission_rates.rate)?, + max_commission: Decimal::from_str(&commission_rates.max_rate)?, + max_change_rate: Decimal::from_str(&commission_rates.max_change_rate)?, + }) + } + + /// Converts the response bytes to a [`IcaQueryResponse`] using the query path. + /// + /// # Errors + /// Returns an error if the response bytes cannot be decoded. + pub fn response( + path: &str, + resp: &[u8], + is_stargate: bool, + ) -> Result { + if is_stargate { + return Ok(IcaQueryResponse::Stargate { + data: Binary(resp.to_vec()), + path: path.to_string(), + }); + } + + match path { + x if x.starts_with("/cosmos.bank.v1beta1.Query/") => bank_response(path, resp), + #[cfg(feature = "staking")] + x if x.starts_with("/cosmos.staking.v1beta1.Query/") => staking_response(path, resp), + _ => Err(ContractError::UnknownDataType(path.to_string())), + } + } + + fn bank_response(path: &str, resp: &[u8]) -> Result { + match path { + constants::BALANCE => { + let resp = QueryBalanceResponse::decode(resp)?; + Ok(IcaQueryResponse::Bank(BankQueryResponse::Balance( + BalanceResponse::new( + resp.balance + .map_or_else(|| Ok(Coin::default()), convert_to_coin)?, + ), + ))) + } + constants::ALL_BALANCES => { + let resp = QueryAllBalancesResponse::decode(resp)?; + Ok(IcaQueryResponse::Bank(BankQueryResponse::AllBalances( + AllBalanceResponse::new( + resp.balances + .into_iter() + .map(convert_to_coin) + .collect::>()?, + ), + ))) + } + constants::DENOM_METADATA => { + let resp = QueryDenomMetadataResponse::decode(resp)?; + Ok(IcaQueryResponse::Bank(BankQueryResponse::DenomMetadata( + DenomMetadataResponse::new( + resp.metadata + .map_or_else(DenomMetadata::default, convert_to_metadata), + ), + ))) + } + constants::ALL_DENOM_METADATA => { + let resp = QueryDenomsMetadataResponse::decode(resp)?; + Ok(IcaQueryResponse::Bank(BankQueryResponse::AllDenomMetadata( + AllDenomMetadataResponse::new( + resp.metadatas + .into_iter() + .map(convert_to_metadata) + .collect(), + resp.pagination + .map(|pagination| Binary(pagination.next_key)), + ), + ))) + } + constants::SUPPLY => { + let resp = QuerySupplyOfResponse::decode(resp)?; + Ok(IcaQueryResponse::Bank(BankQueryResponse::Supply( + SupplyResponse::new( + resp.amount + .map_or_else(|| Ok(Coin::default()), convert_to_coin)?, + ), + ))) + } + _ => Err(ContractError::UnknownDataType(path.to_string())), + } + } + + #[cfg(feature = "staking")] + fn staking_response(path: &str, resp: &[u8]) -> Result { + use super::{ + Delegation, IcaAllDelegationsResponse, IcaDelegationResponse, StakingQueryResponse, + }; + + use cosmos_sdk_proto::cosmos::staking::v1beta1::{ + QueryDelegationResponse, QueryDelegatorDelegationsResponse, QueryParamsResponse, + QueryValidatorResponse, QueryValidatorsResponse, + }; + use cosmwasm_std::{AllValidatorsResponse, BondedDenomResponse, ValidatorResponse}; + + match path { + constants::VALIDATOR => { + let resp = QueryValidatorResponse::decode(resp)?; + Ok(IcaQueryResponse::Staking(StakingQueryResponse::Validator( + ValidatorResponse::new(resp.validator.map(convert_to_validator).transpose()?), + ))) + } + constants::ALL_VALIDATORS => { + let resp = QueryValidatorsResponse::decode(resp)?; + Ok(IcaQueryResponse::Staking( + StakingQueryResponse::AllValidators(AllValidatorsResponse::new( + resp.validators + .into_iter() + .map(convert_to_validator) + .collect::>()?, + )), + )) + } + constants::DELEGATION => { + let resp = QueryDelegationResponse::decode(resp)?; + Ok(IcaQueryResponse::Staking(StakingQueryResponse::Delegation( + IcaDelegationResponse { + delegation: resp + .delegation_response + .and_then(|del_resp| { + del_resp.delegation.map(|del| -> StdResult<_> { + Ok(Delegation { + delegator: del.delegator_address, + validator: del.validator_address, + amount: convert_to_coin( + del_resp.balance.unwrap_or_default(), + )?, + }) + }) + }) + .transpose()?, + }, + ))) + } + constants::ALL_DELEGATIONS => { + let resp = QueryDelegatorDelegationsResponse::decode(resp)?; + Ok(IcaQueryResponse::Staking( + StakingQueryResponse::AllDelegations(IcaAllDelegationsResponse { + delegations: resp + .delegation_responses + .into_iter() + .filter_map(|del_resp| { + del_resp.delegation.map(|del| -> StdResult<_> { + Ok(Delegation { + delegator: del.delegator_address, + validator: del.validator_address, + amount: convert_to_coin( + del_resp.balance.unwrap_or_default(), + )?, + }) + }) + }) + .collect::>()?, + }), + )) + } + constants::STAKING_PARAMS => { + let resp = QueryParamsResponse::decode(resp)?; + Ok(IcaQueryResponse::Staking( + StakingQueryResponse::BondedDenom(BondedDenomResponse::new( + resp.params + .ok_or_else(|| ContractError::EmptyResponse(path.to_string()))? + .bond_denom, + )), + )) + } + _ => Err(ContractError::UnknownDataType(path.to_string())), + } + } +} + +/// This module defines the protobuf messages for the query module. +/// This module can be removed once these types are included in `cosmos_sdk_proto` crate. +// TODO: Remove this module once the types are included in `cosmos_sdk_proto` crate. +pub mod proto { + /// `MsgModuleQuerySafe` defines the query request tx added in ibc-go v8.2 + #[derive(::prost::Message)] + pub struct MsgModuleQuerySafe { + #[prost(string, tag = "1")] + /// signer is the address of the account that signed the transaction + pub signer: ::prost::alloc::string::String, + /// requests is the list of query requests + #[prost(message, repeated, tag = "2")] + pub requests: ::prost::alloc::vec::Vec, + } + + /// `AbciQueryRequest` defines the parameters for a particular query request by an interchain account. + #[derive(::prost::Message)] + pub struct AbciQueryRequest { + #[prost(string, tag = "1")] + /// `path` defines the path of the query request as defined by + /// [ADR-021](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-021-protobuf-query-encoding.md#custom-query-registration-and-routing). + pub path: ::prost::alloc::string::String, + #[prost(bytes = "vec", tag = "2")] + /// `data` defines the payload of the query request as defined by ADR-021. + /// [ADR-021](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-021-protobuf-query-encoding.md#custom-query-registration-and-routing). + pub data: ::prost::alloc::vec::Vec, + } + + /// `MsgModuleQuerySafeResponse` defines the response for Msg/ModuleQuerySafe + #[derive(::prost::Message)] + pub struct MsgModuleQuerySafeResponse { + /// height is the block height at which the query was executed + #[prost(uint64, tag = "1")] + pub height: u64, + /// responses is the list of query responses as bytes + /// The responses are in the same order as the requests + #[prost(bytes = "vec", repeated, tag = "2")] + pub responses: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + } + + impl ::prost::Name for MsgModuleQuerySafe { + const NAME: &'static str = "MsgModuleQuerySafe"; + const PACKAGE: &'static str = "ibc.applications.interchain_accounts.host.v1"; + } +} diff --git a/src/types/state.rs b/src/types/state.rs index d3b01fcd..afd113d9 100644 --- a/src/types/state.rs +++ b/src/types/state.rs @@ -7,7 +7,7 @@ use cw_storage_plus::Item; use super::{msg::options::ChannelOpenInitOptions, ContractError}; #[allow(clippy::module_name_repetitions)] -pub use channel::{State as ChannelState, Status as ChannelStatus}; +pub use channel::{ChannelState, ChannelStatus}; #[allow(clippy::module_name_repetitions)] pub use contract::State as ContractState; @@ -29,6 +29,18 @@ pub const ALLOW_CHANNEL_OPEN_INIT: Item = Item::new("allow_channel_open_in /// Used to prevent relayers from closing channels. This right is reserved to the contract. pub const ALLOW_CHANNEL_CLOSE_INIT: Item = Item::new("allow_channel_close_init"); +/// The item used to store the paths of an ICA query until its `SendPacket` response is received. +/// Once the response is received, it is moved to the [`PENDING_QUERIES`] map and deleted from this item. +/// This is used to ensure that the correct sequence is recorded for the response. +#[cfg(feature = "query")] +pub const QUERY: Item> = Item::new("pending_query"); + +/// `PENDING_QUERIES` is the map of pending queries. +/// It maps `channel_id`, and sequence to the query path. +#[cfg(feature = "query")] +pub const PENDING_QUERIES: cw_storage_plus::Map<(&str, u64), Vec<(String, bool)>> = + cw_storage_plus::Map::new("pending_queries"); + mod contract { use crate::ibc::types::metadata::TxEncoding; @@ -111,6 +123,7 @@ mod contract { } } +#[allow(clippy::module_name_repetitions)] mod channel { use cosmwasm_std::IbcOrder; @@ -118,7 +131,7 @@ mod channel { /// Status is the status of an IBC channel. #[cw_serde] - pub enum Status { + pub enum ChannelStatus { /// Uninitialized is the default state of the channel. #[serde(rename = "STATE_UNINITIALIZED_UNSPECIFIED")] Uninitialized, @@ -147,32 +160,32 @@ mod channel { /// State is the state of the IBC application's channel. /// This application only supports one channel. #[cw_serde] - pub struct State { + pub struct ChannelState { /// The IBC channel, as defined by cosmwasm. pub channel: IbcChannel, /// The status of the channel. - pub channel_status: Status, + pub channel_status: ChannelStatus, } - impl State { + impl ChannelState { /// Creates a new [`ChannelState`] #[must_use] pub const fn new_open_channel(channel: IbcChannel) -> Self { Self { channel, - channel_status: Status::Open, + channel_status: ChannelStatus::Open, } } /// Checks if the channel is open #[must_use] pub const fn is_open(&self) -> bool { - matches!(self.channel_status, Status::Open) + matches!(self.channel_status, ChannelStatus::Open) } /// Closes the channel pub fn close(&mut self) { - self.channel_status = Status::Closed; + self.channel_status = ChannelStatus::Closed; } /// Checks if the channel is [`IbcOrder::Ordered`] @@ -182,7 +195,7 @@ mod channel { } } - impl std::fmt::Display for Status { + impl std::fmt::Display for ChannelStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Uninitialized => write!(f, "STATE_UNINITIALIZED_UNSPECIFIED"), @@ -197,6 +210,25 @@ mod channel { } } +/// This module defines the types stored in the state for ICA queries. +#[cfg(feature = "query")] +pub mod ica_query { + use super::cw_serde; + + /// PendingQuery is the query packet that is pending a response. + #[cw_serde] + pub struct PendingQuery { + /// The source channel ID of the query packet. + pub channel_id: String, + /// The sequence number of the query packet. + pub sequence: u64, + /// The gRPC query path. + pub path: String, + /// Whether the query was [`cosmwasm_std::QueryRequest::Stargate`] or not. + pub is_stargate: bool, + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/testing/contracts/callback-counter/Cargo.lock b/testing/contracts/callback-counter/Cargo.lock index 21cc3913..fd203d16 100644 --- a/testing/contracts/callback-counter/Cargo.lock +++ b/testing/contracts/callback-counter/Cargo.lock @@ -13,6 +13,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anybuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5f1dee23caf80904249463cc4493b6789c2250f88c8f8d9160de5c6099bfe7" + [[package]] name = "anyhow" version = "1.0.86" @@ -37,6 +58,12 @@ 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.6.0" @@ -73,6 +100,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -103,23 +136,48 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + [[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 = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cosmos-sdk-proto" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" +checksum = "82e23f6ab56d5f031cde05b8b82a5fefd3a1a223595c79e32317a97189e612bc" dependencies = [ "prost", "prost-types", @@ -179,7 +237,7 @@ version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ - "base64", + "base64 0.21.7", "bech32", "bnum", "cosmwasm-crypto", @@ -252,6 +310,7 @@ dependencies = [ name = "cw-ica-controller" version = "0.6.0" dependencies = [ + "anybuf", "cosmos-sdk-proto", "cosmwasm-schema", "cosmwasm-std", @@ -259,10 +318,12 @@ dependencies = [ "cw-ownable", "cw-storage-plus", "cw2", + "prost", "schemars", "semver", "serde", "serde-json-wasm 1.0.1", + "serde_with", "thiserror", ] @@ -344,6 +405,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.66", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.66", +] + [[package]] name = "der" version = "0.7.9" @@ -361,6 +457,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -422,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek", - "hashbrown", + "hashbrown 0.12.3", "hex", "rand_core 0.6.4", "serde", @@ -455,6 +552,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ff" version = "0.13.0" @@ -474,6 +577,12 @@ dependencies = [ "paste", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "forward_ref" version = "1.0.0" @@ -522,6 +631,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hex" version = "0.4.3" @@ -537,6 +652,57 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + [[package]] name = "itertools" version = "0.12.1" @@ -552,6 +718,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "k256" version = "0.13.1" @@ -572,6 +747,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "num-conv" version = "0.1.0" @@ -580,13 +761,13 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-derive" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -826,6 +1007,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sha2" version = "0.9.9" @@ -876,6 +1087,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.5.0" @@ -915,9 +1132,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" dependencies = [ "bytes", "flex-error", @@ -958,8 +1175,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", + "serde", "time-core", "time-macros", ] @@ -1004,6 +1223,133 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zeroize" version = "1.8.1" diff --git a/testing/contracts/callback-counter/Cargo.toml b/testing/contracts/callback-counter/Cargo.toml index f0538185..308a7eda 100644 --- a/testing/contracts/callback-counter/Cargo.toml +++ b/testing/contracts/callback-counter/Cargo.toml @@ -42,7 +42,7 @@ cosmwasm-std = { version = "1.4.0", features = [ ] } cw-storage-plus = "1.1.0" cw2 = "1.1.0" -cw-ica-controller = { path = "../../..", default-features = false } +cw-ica-controller = { path = "../../..", default-features = false, features = ["query", "staking"] } schemars = "0.8.10" serde = { version = "1.0.145", default-features = false, features = ["derive"] } serde-json-wasm = "0.5.1" diff --git a/testing/contracts/cw-ica-owner/Cargo.lock b/testing/contracts/cw-ica-owner/Cargo.lock index dc4aec7b..b2c7fc83 100644 --- a/testing/contracts/cw-ica-owner/Cargo.lock +++ b/testing/contracts/cw-ica-owner/Cargo.lock @@ -13,6 +13,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anybuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5f1dee23caf80904249463cc4493b6789c2250f88c8f8d9160de5c6099bfe7" + [[package]] name = "anyhow" version = "1.0.86" @@ -43,6 +64,12 @@ 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.6.0" @@ -79,6 +106,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -94,23 +127,48 @@ dependencies = [ "serde", ] +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + [[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 = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "cosmos-sdk-proto" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" +checksum = "82e23f6ab56d5f031cde05b8b82a5fefd3a1a223595c79e32317a97189e612bc" dependencies = [ "prost 0.12.6", "prost-types", @@ -170,7 +228,7 @@ version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ - "base64", + "base64 0.21.7", "bech32", "bnum", "cosmwasm-crypto", @@ -255,6 +313,7 @@ dependencies = [ name = "cw-ica-controller" version = "0.6.0" dependencies = [ + "anybuf", "cosmos-sdk-proto", "cosmwasm-schema", "cosmwasm-std", @@ -266,6 +325,7 @@ dependencies = [ "semver", "serde", "serde-json-wasm 1.0.1", + "serde_with", "thiserror", ] @@ -382,6 +442,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.66", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.66", +] + [[package]] name = "der" version = "0.6.1" @@ -409,6 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -482,7 +578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek", - "hashbrown", + "hashbrown 0.12.3", "hex", "rand_core 0.6.4", "serde", @@ -535,6 +631,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ff" version = "0.12.1" @@ -564,6 +666,12 @@ dependencies = [ "paste", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "forward_ref" version = "1.0.0" @@ -623,6 +731,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hex" version = "0.4.3" @@ -638,6 +752,57 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[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", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + [[package]] name = "itertools" version = "0.10.5" @@ -662,6 +827,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "k256" version = "0.11.6" @@ -694,6 +868,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "num-conv" version = "0.1.0" @@ -702,13 +882,13 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-derive" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1006,6 +1186,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sha2" version = "0.9.9" @@ -1076,6 +1286,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.5.0" @@ -1115,9 +1331,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" dependencies = [ "bytes", "flex-error", @@ -1158,8 +1374,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", + "serde", "time-core", "time-macros", ] @@ -1204,6 +1422,133 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zeroize" version = "1.8.1"