├── .cargo └── config.toml ├── .editorconfig ├── .env.example ├── .gitattributes ├── .github ├── codecov.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── check.yml │ ├── coverage.yml │ ├── gh-pages.yml │ └── test.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.toml ├── INSTALL.md ├── LICENSE ├── LICENSE.LESSER ├── MIGRATING.md ├── README.md ├── artifacts ├── checksums.txt ├── counter_contract.wasm ├── cw_orch_compatibility_test.wasm ├── mock_contract.wasm └── mock_contract_u64.wasm ├── before_publish.sh ├── contracts-ws ├── Cargo.toml └── contracts │ ├── counter │ ├── Cargo.toml │ ├── README.md │ ├── artifacts │ ├── examples │ │ ├── async.rs │ │ └── deploy.rs │ ├── src │ │ ├── contract.rs │ │ ├── error.rs │ │ ├── execute.rs │ │ ├── interface.rs │ │ ├── lib.rs │ │ ├── msg.rs │ │ ├── query.rs │ │ └── state.rs │ └── tests │ │ ├── checksum.rs │ │ └── integration_tests.rs │ ├── mock_contract │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── custom_resp.rs │ │ ├── lib.rs │ │ └── msg_tests.rs │ └── mock_contract_u64 │ ├── Cargo.toml │ ├── README.md │ └── src │ └── lib.rs ├── cw-orch-daemon ├── Cargo.toml ├── README.md ├── examples │ ├── batch-sender.rs │ ├── daemon-capabilities.rs │ ├── hd_index.rs │ ├── manual_sender.rs │ └── querier-daemon.rs ├── src │ ├── builder.rs │ ├── channel.rs │ ├── core.rs │ ├── env.rs │ ├── error.rs │ ├── json_lock.rs │ ├── keys │ │ ├── mod.rs │ │ ├── private.rs │ │ ├── public.rs │ │ └── signature.rs │ ├── lib.rs │ ├── live_mock.rs │ ├── log.rs │ ├── network_config.rs │ ├── proto │ │ ├── injective.rs │ │ └── mod.rs │ ├── queriers.rs │ ├── queriers │ │ ├── authz.rs │ │ ├── bank.rs │ │ ├── cosmwasm.rs │ │ ├── env.rs │ │ ├── feegrant.rs │ │ ├── gov.rs │ │ ├── ibc.rs │ │ ├── node.rs │ │ └── staking.rs │ ├── senders │ │ ├── builder.rs │ │ ├── cosmos.rs │ │ ├── cosmos_batch.rs │ │ ├── cosmos_options.rs │ │ ├── mod.rs │ │ ├── query.rs │ │ ├── query_only.rs │ │ ├── sign.rs │ │ └── tx.rs │ ├── state.rs │ ├── sync │ │ ├── builder.rs │ │ ├── core.rs │ │ └── mod.rs │ ├── tx_broadcaster.rs │ ├── tx_builder.rs │ └── tx_resp.rs └── tests │ ├── authz.rs │ ├── common │ └── mod.rs │ ├── daemon_helpers.rs │ ├── daemon_state.rs │ ├── index.rs │ ├── instantiate2.rs │ ├── mock_networks.toml │ ├── querier.rs │ └── tx_resp.rs ├── cw-orch-interchain ├── Cargo.toml ├── examples │ ├── doc_daemon.rs │ ├── doc_mock.rs │ ├── follow_packets_txhash.rs │ ├── manual_ica_demo.rs │ ├── starship_ica_demo.rs │ └── timeout_packet.rs ├── src │ └── lib.rs ├── tests │ ├── common │ │ ├── ica_demo.rs │ │ └── mod.rs │ ├── mock_ica_demo.rs │ ├── mock_transfer.rs │ └── timeout_packet_mock.rs └── wasms │ ├── cw1_whitelist.wasm │ ├── simple_ica_controller.wasm │ └── simple_ica_host.wasm ├── cw-orch ├── Cargo.toml ├── README.md ├── examples │ ├── async_daemon.rs │ ├── automatic-into.rs │ ├── complex_testnet_daemon.rs │ ├── injective.rs │ ├── local_daemon.rs │ ├── mock.rs │ ├── mockbech32.rs │ ├── queries │ │ ├── bank_query.rs │ │ └── testnet_queries.rs │ └── testnet_daemon.rs ├── src │ ├── daemon.rs │ ├── error.rs │ ├── lib.rs │ ├── prelude.rs │ ├── snapshots.rs │ └── snapshots │ │ ├── cw_orch__snapshots__tests__multiple_contracts_snapshot_test.snap │ │ └── cw_orch__snapshots__tests__snapshot_test.snap └── tests │ ├── entry_point_macro.rs │ ├── fns_macro.rs │ ├── interface_macro.rs │ ├── interface_macro_generics.rs │ ├── new_chain.rs │ └── underlying_into.rs ├── docs ├── .gitignore ├── book.toml └── src │ ├── SUMMARY.md │ ├── chain-specific-quick-start.md │ ├── chains │ ├── archway.md │ ├── bitsong.md │ ├── cosmos.md │ ├── index.md │ ├── injective.md │ ├── juno.md │ ├── kujira.md │ ├── landslide.md │ ├── migaloo.md │ ├── neutron.md │ ├── nibiru.md │ ├── osmosis.md │ ├── rollkit.md │ ├── sei.md │ ├── terra.md │ ├── union.md │ └── xion.md │ ├── ci-cd.md │ ├── cli │ ├── cosmos_action.md │ ├── index.md │ └── keys.md │ ├── contracts │ ├── entry-points.md │ ├── env-variable.md │ ├── index.md │ ├── integration-tests.md │ ├── interfaces.md │ ├── scripting.md │ └── wasm-compilation.md │ ├── contributing.md │ ├── integrations │ ├── clone-testing.md │ ├── cw-multi-test.md │ ├── daemon.md │ ├── index.md │ ├── osmosis-test-tube.md │ └── unit-tests.md │ ├── interchain │ ├── index.md │ ├── integrations │ │ ├── daemon.md │ │ ├── index.md │ │ ├── mock.md │ │ └── starship.md │ └── quick-start.md │ ├── intro.md │ ├── quick_start.md │ ├── references.md │ └── setup │ ├── index.md │ ├── single-contract.md │ └── workspace │ ├── collaboration.md │ ├── deploy.md │ ├── index.md │ └── setup.md ├── hooks └── pre-push.sh ├── justfile ├── networks.toml.example ├── packages ├── clone-testing │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── contract_instance.rs │ │ ├── core.rs │ │ ├── lib.rs │ │ ├── queriers │ │ │ ├── bank.rs │ │ │ ├── env.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ └── wasm.rs │ │ └── state.rs │ └── tests │ │ ├── clone-testing.rs │ │ └── wasm-upload.rs ├── cw-orch-core │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── build.rs │ │ ├── contract │ │ ├── contract_instance.rs │ │ ├── deploy.rs │ │ ├── interface_traits.rs │ │ ├── mod.rs │ │ └── paths.rs │ │ ├── env.rs │ │ ├── environment │ │ ├── chain_info.rs │ │ ├── envs.rs │ │ ├── index_response.rs │ │ ├── mod.rs │ │ ├── queriers │ │ │ ├── bank.rs │ │ │ ├── env.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ └── wasm.rs │ │ ├── state.rs │ │ └── tx_handler.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ └── log.rs ├── cw-orch-mock │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── bech32.rs │ │ ├── core.rs │ │ ├── lib.rs │ │ ├── queriers │ │ │ ├── bank.rs │ │ │ ├── env.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ └── wasm.rs │ │ ├── simple.rs │ │ └── state.rs │ └── tests │ │ ├── conditional.rs │ │ └── instantiate2.rs ├── cw-orch-networks │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── lib.rs │ │ └── networks │ │ ├── archway.rs │ │ ├── bitsong.rs │ │ ├── cosmos.rs │ │ ├── doravota.rs │ │ ├── injective.rs │ │ ├── juno.rs │ │ ├── kujira.rs │ │ ├── landslide.rs │ │ ├── migaloo.rs │ │ ├── mod.rs │ │ ├── neutron.rs │ │ ├── nibiru.rs │ │ ├── osmosis.rs │ │ ├── rollkit.rs │ │ ├── sei.rs │ │ ├── terra.rs │ │ ├── union.rs │ │ └── xion.rs ├── cw-orch-neutron-test-tube │ ├── Cargo.toml │ ├── src │ │ ├── core.rs │ │ ├── lib.rs │ │ └── queriers │ │ │ ├── bank.rs │ │ │ ├── env.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ └── wasm.rs │ └── tests │ │ └── neutron_test_tube.rs ├── cw-orch-osmosis-test-tube │ ├── Cargo.toml │ ├── examples │ │ ├── basic.rs │ │ └── complex.rs │ ├── src │ │ ├── core.rs │ │ ├── lib.rs │ │ └── queriers │ │ │ ├── bank.rs │ │ │ ├── env.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ └── wasm.rs │ └── tests │ │ └── osmosis-test-tube.rs ├── cw-orch-traits │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── lib.rs │ │ └── stargate.rs ├── integrations │ └── cw-plus │ │ ├── Cargo.toml │ │ ├── examples │ │ ├── download_wasms.rs │ │ └── test_wasm.rs │ │ ├── src │ │ ├── cw1_subkeys.rs │ │ ├── cw1_whitelist.rs │ │ ├── cw20_base.rs │ │ ├── cw20_ics20.rs │ │ ├── cw3_fixed_multisig.rs │ │ ├── cw3_flex_multisig.rs │ │ ├── cw4_group.rs │ │ ├── cw4_stake.rs │ │ └── lib.rs │ │ └── tests │ │ └── interface_tests.rs ├── interchain │ ├── interchain-core │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── ack_parser.rs │ │ │ ├── analysis.rs │ │ │ ├── channel.rs │ │ │ ├── env.rs │ │ │ ├── error.rs │ │ │ ├── ibc_query.rs │ │ │ ├── lib.rs │ │ │ ├── packet.rs │ │ │ ├── results.rs │ │ │ └── tx.rs │ ├── interchain-daemon │ │ ├── Cargo.toml │ │ ├── examples │ │ │ └── starship_channel.rs │ │ └── src │ │ │ ├── channel_creator.rs │ │ │ ├── error.rs │ │ │ ├── ibc_tracker.rs │ │ │ ├── interchain_env.rs │ │ │ ├── interchain_log.rs │ │ │ ├── lib.rs │ │ │ └── packet_inspector.rs │ ├── interchain-mock │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src │ │ │ ├── error.rs │ │ │ ├── interchain.rs │ │ │ └── lib.rs │ ├── proto │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── tokenfactory.rs │ └── starship │ │ ├── Cargo.toml │ │ ├── examples │ │ └── starship.yaml │ │ ├── src │ │ ├── client │ │ │ ├── core.rs │ │ │ ├── error.rs │ │ │ ├── faucet.rs │ │ │ ├── mod.rs │ │ │ └── registry.rs │ │ └── lib.rs │ │ └── starship │ │ ├── Makefile │ │ ├── README.md │ │ └── port-forward.sh └── macros │ ├── cw-orch-contract-derive │ ├── Cargo.toml │ └── src │ │ └── lib.rs │ ├── cw-orch-fns-derive │ ├── Cargo.toml │ └── src │ │ ├── fns_derive.rs │ │ ├── helpers.rs │ │ ├── lib.rs │ │ └── query_fns.rs │ └── from-interface-derive │ ├── Cargo.toml │ └── src │ └── lib.rs ├── publish.sh ├── rustfmt.toml ├── taplo.toml ├── test_contracts └── compatibility-test │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── lib.rs │ └── msg_tests.rs └── wasm_contracts.sh /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | bl = "build --features daemon" 3 | ch = "check --features daemon" 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.rs] 11 | indent_size = 4 12 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | 2 | # info, debug, trace (if using env_logger for logging) 3 | RUST_LOG=info 4 | 5 | # Optional. This is the name of the state file from $CW_ORCH_STATE_FOLDER e.g. here ~/.cw-orchestrator/state.json. Defaults to state.json 6 | STATE_FILE="state.json" 7 | 8 | # Optional 9 | # Where the contract wasms are located (used by ArtifactsDir::env()) 10 | ARTIFACTS_DIR="artifacts_dir" 11 | 12 | MAIN_MNEMONIC="" # Necessary if interacting with a cw-orch-daemon on mainnet 13 | TEST_MNEMONIC="" # Necessary if interacting with a cw-orch-daemon on testnet 14 | LOCAL_MNEMONIC="" # Necessary if interacting with a cw-orch-daemon locally 15 | 16 | ## Additional configuration variables. These are optional. We show default values here : 17 | # Optional - Float. This allows changing the gas buffer applied after tx simulation 18 | CW_ORCH_GAS_BUFFER = 1.3 19 | # Optional - Integer. This changes the number of tx queries before it fails if it doesn't find any result 20 | CW_ORCH_MAX_TX_QUERY_RETRIES = 50 21 | # Optional - Integer. Minimum block speed in seconds. Useful when the block speeds are varying a lot 22 | CW_ORCH_MIN_BLOCK_SPEED = 1 23 | # Optional - String. If equals to "true", will serialize the blockchain messages as json (for easy copying) instead of Rust Debug formatting 24 | CW_ORCH_SERIALIZE_JSON = "false" 25 | # Optional - Absolute Path. Sets the directory where the state file will be saved. 26 | # This is not enforced to be an absolute path but this is highly recommended 27 | CW_ORCH_STATE_FOLDER = "~/.cw-orchestrator" -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docs/book linguist-generated=true 2 | *.snap linguist-generated=true 3 | *.snap.new linguist-generated=true -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | # ref: https://docs.codecov.com/docs/codecovyml-reference 2 | coverage: 3 | # Hold ourselves to a high bar 4 | range: 85..100 5 | round: down 6 | precision: 1 7 | status: 8 | # ref: https://docs.codecov.com/docs/commit-status 9 | project: 10 | default: 11 | # Avoid false negatives 12 | threshold: 1% 13 | 14 | # Test files aren't important for coverage 15 | ignore: 16 | - "tests" 17 | - "**/examples" 18 | - "**/schema.rs" 19 | 20 | # Make comments less noisy 21 | comment: 22 | layout: "files" 23 | require_changes: true 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: cargo 8 | directory: / 9 | schedule: 10 | interval: daily 11 | ignore: 12 | - dependency-name: "*" 13 | # patch and minor updates don't matter for libraries 14 | # remove this ignore rule if your package has binaries 15 | update-types: 16 | - "version-update:semver-patch" 17 | - "version-update:semver-minor" 18 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Checklist 2 | 3 | - [ ] Changelog updated. 4 | - [ ] Docs updated. 5 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | permissions: 2 | contents: read 3 | on: 4 | push: 5 | branches: [main] 6 | name: test 7 | env: 8 | CODECOV_TOKEN: 62fac3fe-498a-4449-a00d-a9b30b443acf 9 | jobs: 10 | coverage: 11 | runs-on: ubuntu-latest 12 | name: ubuntu / stable / coverage 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | submodules: true 17 | - name: Install stable 18 | uses: dtolnay/rust-toolchain@stable 19 | with: 20 | components: llvm-tools-preview 21 | - name: Free up disk space on runner 22 | run: | 23 | df -h 24 | rm -rf /usr/share/dotnet/ 25 | sudo apt-get remove -y 'php.*' || true 26 | sudo apt-get remove -y '^dotnet-.*' || true 27 | sudo apt-get remove -y azure-cli firefox powershell mono-devel || true 28 | sudo apt-get autoremove -y || true 29 | sudo apt-get clean || true 30 | df -h 31 | shell: bash 32 | - name: cargo install cargo-llvm-cov 33 | uses: taiki-e/install-action@cargo-llvm-cov 34 | - name: cargo generate-lockfile 35 | if: hashFiles('Cargo.lock') == '' 36 | run: cargo generate-lockfile 37 | - name: cargo llvm-cov 38 | run: cargo llvm-cov --locked --all-features --lcov --output-path lcov.info 39 | - name: Upload to codecov.io 40 | uses: codecov/codecov-action@v4 41 | with: 42 | fail_ci_if_error: true 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target 4 | scripts 5 | 6 | **/*.json 7 | 8 | .env 9 | !example.env 10 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 11 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 12 | Cargo.lock 13 | .vscode 14 | # These are backup files generated by rustfmt 15 | **/*.rs.bk 16 | *_bak 17 | 18 | .DS_Store 19 | **/profraw_data/ 20 | gen_cov_test 21 | 22 | **/logs/ 23 | 24 | docs/book 25 | 26 | packages/integrations/**/artifacts 27 | -------------------------------------------------------------------------------- /MIGRATING.md: -------------------------------------------------------------------------------- 1 | # Migrating cw-orch 2 | 3 | This guide explains how to upgrade cw-orch in your contracts. 4 | 5 | ## cw-orch-core 1.x.x -> 2.x.x (Cosmwasm 2.0) 6 | 7 | - Update cw-orch dependencies 8 | 9 | ```diff 10 | -cw-orch = { version = "0.24.0" } 11 | -cw-orch-interchain = { version = "0.3.0" } 12 | +cw-orch = { version = "0.25.0" } 13 | +cw-orch-interchain = { version = "0.4.0" } 14 | ``` 15 | 16 | - Update cosmwasm dependencies 17 | 18 | ```diff 19 | -cosmwasm-std = { version = "1.5.0", features = ["cosmwasm_1_2"] } 20 | -cosmwasm-schema = { version = "1.2" } 21 | -cw-controllers = { version = "1.0" } 22 | -cw-storage-plus = "1.2.0" 23 | +cosmwasm-std = { version = "2.0.0", features = ["cosmwasm_1_2"] } 24 | +cosmwasm-schema = { version = "2.0" } 25 | +cw-controllers = { version = "2.0" } 26 | +cw-storage-plus = "2.0.0" 27 | ``` 28 | 29 | For more detailed cosmwasm migration see: 30 | 31 | - Update cosmwasm specifications dependencies 32 | 33 | ```diff 34 | -cw2 = { version = "1.0" } 35 | -cw20 = { version = "1.0" } 36 | +cw2 = { version = "2.0" } 37 | +cw20 = { version = "2.0" } 38 | ``` 39 | 40 | - Update prost dependencies to 0.13.x 41 | 42 | ```diff 43 | -prost = { version = "0.12.3", default-features = false } 44 | +prost = { version = "0.13.1", default-features = false } 45 | ``` 46 | 47 | - Update cosmos-sdk-proto dependency to 0.24+ 48 | 49 | ```diff 50 | -cosmos-sdk-proto = { version = "0.20.0", default-features = false } 51 | +cosmos-sdk-proto = { version = "0.24.0", default-features = false } 52 | +ibc-proto = { version = "0.47.0" } # ibc types from cosmos-sdk-proto replaced by `ibc-proto` package 53 | ``` 54 | 55 | - `TxHandler::sender()` was deprecated in 1.1.2 and in 2.x.x versions returned value is `&TxHandler::Sender`, instead of `Addr`, for address please use `TxHandler::sender_addr()` 56 | 57 | ```diff 58 | -let sender_addr = chain.sender(); 59 | +let sender_addr = chain.sender_addr(); 60 | ``` 61 | 62 | - Methods from `cw_orch::prelude::Deploy` trait that was related to the daemon state is now inside `cw_orch::daemon::DeployedChains` (feature `daemon` required) 63 | -------------------------------------------------------------------------------- /artifacts/checksums.txt: -------------------------------------------------------------------------------- 1 | cc02664dc02c571fd0e4bb02061b737571a510a6a4ac01f8cc783545bec6fff4 counter_contract.wasm 2 | a266c5ab0ffdf78b3aee593d07d3c822fa3c2745bc7bc8210e49860439d65a73 cw_orch_compatibility_test.wasm 3 | 0dc79fb31e732310554a07881cfe8a193c068d2f93539356817e5aaf551650dd mock_contract.wasm 4 | 08d65b781d7357a6777c836229d971b6c87a5fdfc7cba9806ed508f917859f08 mock_contract_u64.wasm 5 | -------------------------------------------------------------------------------- /artifacts/counter_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/artifacts/counter_contract.wasm -------------------------------------------------------------------------------- /artifacts/cw_orch_compatibility_test.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/artifacts/cw_orch_compatibility_test.wasm -------------------------------------------------------------------------------- /artifacts/mock_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/artifacts/mock_contract.wasm -------------------------------------------------------------------------------- /artifacts/mock_contract_u64.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/artifacts/mock_contract_u64.wasm -------------------------------------------------------------------------------- /before_publish.sh: -------------------------------------------------------------------------------- 1 | cargo run --example download-wasms -p cw-plus-orch 2 | -------------------------------------------------------------------------------- /contracts-ws/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = ["contracts/*"] 4 | 5 | resolver = "2" 6 | 7 | [workspace.package] 8 | edition = "2021" 9 | 10 | [workspace.dependencies] 11 | cosmwasm-std = "2.0.0" 12 | cw-storage-plus = { version = "2.0.0" } 13 | cw20 = { version = "2.0.0" } 14 | cw20-base = { version = "2.0.0" } 15 | 16 | anyhow = "1.0" 17 | log = "0.4.14" 18 | serde = { version = "1.0.103", default-features = false, features = ["derive"] } 19 | 20 | cw-orch = { path = "../cw-orch", version = "0.27.0" } 21 | cw-orch-interchain = { path = "../cw-orch-interchain", version = "0.8.1" } 22 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "counter constract" 3 | edition = { workspace = true } 4 | exclude = [".env"] 5 | keywords = ["cosmwasm", "blockchain"] 6 | license = "LGPL-3.0" 7 | name = "counter-contract" 8 | version = "0.27.1" 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [features] 14 | default = ["export"] 15 | export = [] 16 | 17 | [dependencies] 18 | cosmwasm-schema = "2.1" 19 | cosmwasm-std = { workspace = true } 20 | cw-orch = { workspace = true, features = ["daemon"] } 21 | cw-storage-plus = { workspace = true } 22 | cw2 = "2.0" 23 | schemars = "0.8.21" 24 | serde = { workspace = true } 25 | serde_json = "1.0.125" 26 | thiserror = { version = "1.0.63" } 27 | # Unused, only there to check for wasm compatibility 28 | cw-orch-interchain = { workspace = true, features = ["daemon"] } 29 | 30 | [[example]] 31 | name = "deploy" 32 | 33 | [dev-dependencies] 34 | # Deps for deployment 35 | anyhow = { workspace = true } 36 | cw-orch = { workspace = true, features = ["daemon"] } 37 | dotenv = { version = "0.15.0" } 38 | pretty_env_logger = { version = "0.5.0" } 39 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/README.md: -------------------------------------------------------------------------------- 1 | Refer to [https://orchestrator.abstract.money/](https://orchestrator.abstract.money/) for more details on how to use this crate 2 | 3 | Check out the [examples](./examples) and [tests](./tests) in this crate to understand how to use it by example. 4 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/artifacts: -------------------------------------------------------------------------------- 1 | ../../../artifacts -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/examples/async.rs: -------------------------------------------------------------------------------- 1 | // ANCHOR: full_async_example 2 | use counter_contract::AsyncCounterQueryMsgFns; 3 | use counter_contract::CounterContract; 4 | use cw_orch::{anyhow, prelude::*, tokio}; 5 | 6 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L2 7 | const LOCAL_MNEMONIC: &str = "clip hire initial neck maid actor venue client foam budget lock catalog sweet steak waste crater broccoli pipe steak sister coyote moment obvious choose"; 8 | 9 | #[tokio::main] 10 | pub async fn main() -> anyhow::Result<()> { 11 | std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC); 12 | dotenv::dotenv().ok(); // Used to load the `.env` file if any 13 | pretty_env_logger::init(); // Used to log contract and chain interactions 14 | 15 | let network = networks::LOCAL_JUNO; 16 | let chain = DaemonAsyncBuilder::new(network).build().await?; 17 | 18 | let counter = CounterContract::new(chain); 19 | 20 | let count = counter.get_count_async().await?; 21 | assert_eq!(count.count, 1); 22 | 23 | Ok(()) 24 | } 25 | 26 | // ANCHOR_END: full_async_example 27 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/examples/deploy.rs: -------------------------------------------------------------------------------- 1 | // ANCHOR: full_counter_example 2 | use counter_contract::{ 3 | msg::InstantiateMsg, CounterContract, CounterExecuteMsgFns, CounterQueryMsgFns, 4 | }; 5 | use cw_orch::{anyhow, prelude::*}; 6 | 7 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L2 8 | const LOCAL_MNEMONIC: &str = "clip hire initial neck maid actor venue client foam budget lock catalog sweet steak waste crater broccoli pipe steak sister coyote moment obvious choose"; 9 | pub fn main() -> anyhow::Result<()> { 10 | std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC); 11 | // ANCHOR: chain_construction 12 | dotenv::dotenv().ok(); // Used to load the `.env` file if any 13 | pretty_env_logger::init(); // Used to log contract and chain interactions 14 | 15 | let network = networks::LOCAL_JUNO; 16 | let chain = DaemonBuilder::new(network).build()?; 17 | // ANCHOR_END: chain_construction 18 | 19 | // ANCHOR: contract_interaction 20 | let counter = CounterContract::new(chain); 21 | 22 | // ANCHOR: clean_example 23 | counter.upload()?; 24 | counter.instantiate(&InstantiateMsg { count: 0 }, None, &[])?; 25 | 26 | counter.increment()?; 27 | 28 | let count = counter.get_count()?; 29 | assert_eq!(count.count, 1); 30 | // ANCHOR_END: clean_example 31 | // ANCHOR_END: contract_interaction 32 | 33 | Ok(()) 34 | } 35 | // ANCHOR_END: full_counter_example 36 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/error.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::StdError; 2 | use thiserror::Error; 3 | 4 | #[derive(Error, PartialEq, Debug)] 5 | pub enum ContractError { 6 | #[error("{0}")] 7 | Std(#[from] StdError), 8 | 9 | #[error("Unauthorized")] 10 | Unauthorized {}, 11 | 12 | #[error("Custom Error val: {val:?}")] 13 | CustomError { val: String }, 14 | // Add any other custom errors you like here. 15 | // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. 16 | } 17 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/execute.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::{DepsMut, MessageInfo, Response}; 2 | 3 | use crate::{error::*, state::*}; 4 | 5 | pub fn increment(deps: DepsMut) -> Result { 6 | STATE.update(deps.storage, |mut state| -> Result<_, ContractError> { 7 | state.count += 1; 8 | Ok(state) 9 | })?; 10 | 11 | Ok(Response::new().add_attribute("action", "increment")) 12 | } 13 | 14 | pub fn reset(deps: DepsMut, info: MessageInfo, count: i32) -> Result { 15 | STATE.update(deps.storage, |mut state| -> Result<_, ContractError> { 16 | if info.sender != state.owner { 17 | return Err(ContractError::Unauthorized {}); 18 | } 19 | state.count = count; 20 | Ok(state) 21 | })?; 22 | Ok(Response::new().add_attribute("action", "reset")) 23 | } 24 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod contract; 2 | mod error; 3 | pub(crate) mod execute; 4 | pub mod msg; 5 | pub(crate) mod query; 6 | pub mod state; 7 | 8 | pub use crate::error::ContractError; 9 | // ANCHOR: fn_re_export 10 | pub use crate::msg::{ 11 | AsyncQueryMsgFns as AsyncCounterQueryMsgFns, ExecuteMsgFns as CounterExecuteMsgFns, 12 | QueryMsgFns as CounterQueryMsgFns, 13 | }; 14 | // ANCHOR_END: fn_re_export 15 | 16 | // ANCHOR: custom_interface 17 | #[cfg(not(target_arch = "wasm32"))] 18 | mod interface; 19 | // ANCHOR_END: custom_interface 20 | 21 | // ANCHOR: interface_reexport 22 | #[cfg(not(target_arch = "wasm32"))] 23 | pub use crate::interface::CounterContract; 24 | // ANCHOR_END: interface_reexport 25 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/msg.rs: -------------------------------------------------------------------------------- 1 | #![warn(missing_docs)] 2 | //! # Counter contract 3 | 4 | use cosmwasm_schema::{cw_serde, QueryResponses}; 5 | 6 | #[cw_serde] 7 | /// Instantiate method for counter 8 | pub struct InstantiateMsg { 9 | /// Initial count 10 | pub count: i32, 11 | } 12 | 13 | // ANCHOR: exec_msg 14 | #[cw_serde] 15 | #[derive(cw_orch::ExecuteFns)] // Function generation 16 | /// Execute methods for counter 17 | pub enum ExecuteMsg { 18 | /// Increment count by one 19 | Increment {}, 20 | /// Reset count 21 | Reset { 22 | /// Count value after reset 23 | count: i32, 24 | }, 25 | } 26 | // ANCHOR_END: exec_msg 27 | 28 | // ANCHOR: query_msg 29 | #[cw_serde] 30 | #[derive(cw_orch::QueryFns)] // Function generation 31 | #[derive(QueryResponses)] 32 | /// Query methods for counter 33 | pub enum QueryMsg { 34 | /// GetCount returns the current count as a json-encoded number 35 | #[returns(GetCountResponse)] 36 | GetCount {}, 37 | } 38 | 39 | // Custom response for the query 40 | #[cw_serde] 41 | /// Response from get_count query 42 | pub struct GetCountResponse { 43 | /// Current count in the state 44 | pub count: i32, 45 | } 46 | // ANCHOR_END: query_msg 47 | 48 | #[cw_serde] 49 | /// Migrate message for count contract 50 | pub struct MigrateMsg { 51 | /// Your favorite type of tea 52 | pub t: String, 53 | } 54 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/query.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::{Deps, StdResult}; 2 | 3 | use crate::{msg::GetCountResponse, state::STATE}; 4 | 5 | pub fn count(deps: Deps) -> StdResult { 6 | let state = STATE.load(deps.storage)?; 7 | Ok(GetCountResponse { count: state.count }) 8 | } 9 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/src/state.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_schema::cw_serde; 2 | 3 | use cosmwasm_std::Addr; 4 | use cw_storage_plus::Item; 5 | 6 | #[cw_serde] 7 | pub struct State { 8 | pub count: i32, 9 | pub owner: Addr, 10 | } 11 | 12 | pub const STATE: Item = Item::new("state"); 13 | -------------------------------------------------------------------------------- /contracts-ws/contracts/counter/tests/checksum.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::CounterContract; 2 | use cw_orch::{contract::interface_traits::Uploadable, daemon::networks::OSMOSIS_1, mock::Mock}; 3 | 4 | #[test] 5 | fn checksum() { 6 | use std::fs::File; 7 | use std::io::{self, BufRead}; 8 | use std::path::Path; 9 | 10 | let path = Path::new("../../../artifacts/checksums.txt"); 11 | let file = File::open(path).unwrap(); 12 | let lines = io::BufReader::new(file).lines(); 13 | let mut found = false; 14 | 15 | for line in lines.map_while(Result::ok) { 16 | if line.contains("counter_contract.wasm") { 17 | let parts: Vec<&str> = line.split_whitespace().collect(); 18 | if parts.len() > 1 { 19 | let calculated_hash = CounterContract::::wasm(&OSMOSIS_1.into()) 20 | .checksum() 21 | .unwrap(); 22 | assert_eq!(parts[0], calculated_hash.to_string()); 23 | found = true; 24 | break; 25 | } 26 | } 27 | } 28 | 29 | if !found { 30 | panic!("Checksum of counter_contract.wasm not found in checksums.txt"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts-ws/contracts/mock_contract/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "Mock constract for cw-orch macro testing" 3 | edition = { workspace = true } 4 | keywords = ["cosmwasm", "blockchain"] 5 | name = "mock-contract" 6 | version = "0.1.0" 7 | 8 | exclude = [".env"] 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [features] 14 | default = ["export"] 15 | export = [] 16 | interface = [] 17 | 18 | [dependencies] 19 | cosmwasm-schema = "2.1" 20 | cosmwasm-std = { workspace = true } 21 | cw-orch = { workspace = true } 22 | cw-storage-plus = { workspace = true } 23 | cw2 = { version = "2.0.0" } 24 | schemars = "0.8.21" 25 | serde = { workspace = true } 26 | serde_json = "1.0.125" 27 | thiserror = { version = "1.0.63" } 28 | -------------------------------------------------------------------------------- /contracts-ws/contracts/mock_contract/README.md: -------------------------------------------------------------------------------- 1 | # Mock Contract test 2 | 3 | This folder is used for testing. 4 | -------------------------------------------------------------------------------- /contracts-ws/contracts/mock_contract/src/custom_resp.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | use cosmwasm_schema::{cw_serde, QueryResponses}; 3 | use cosmwasm_std::{ 4 | to_json_binary, Binary, CustomMsg, CustomQuery, Deps, DepsMut, Env, MessageInfo, Response, 5 | StdError, StdResult, Uint128, 6 | }; 7 | 8 | #[cw_serde] 9 | pub struct A; 10 | 11 | impl CustomMsg for A {} 12 | impl CustomQuery for A {} 13 | 14 | #[cw_serde] 15 | pub struct InstantiateMsg {} 16 | 17 | #[cw_serde] 18 | #[derive(cw_orch::ExecuteFns)] 19 | pub enum ExecuteMsg { 20 | FirstMessage {}, 21 | } 22 | 23 | #[cw_serde] 24 | #[derive(cw_orch::QueryFns, QueryResponses)] 25 | pub enum QueryMsg { 26 | #[returns(String)] 27 | FirstQuery {}, 28 | #[returns(String)] 29 | SecondQuery { t: String }, 30 | } 31 | 32 | #[cw_serde] 33 | pub struct MigrateMsg { 34 | pub t: String, 35 | } 36 | 37 | pub fn instantiate( 38 | _deps: DepsMut, 39 | _env: Env, 40 | _info: MessageInfo, 41 | _msg: InstantiateMsg, 42 | ) -> StdResult> { 43 | Ok(Response::new().add_attribute("action", "instantiate")) 44 | } 45 | 46 | pub fn execute( 47 | _deps: DepsMut, 48 | _env: Env, 49 | _info: MessageInfo, 50 | msg: ExecuteMsg, 51 | ) -> StdResult> { 52 | match msg { 53 | ExecuteMsg::FirstMessage {} => { 54 | Ok(Response::new().add_attribute("action", "first message passed")) 55 | } 56 | } 57 | } 58 | 59 | pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { 60 | match msg { 61 | QueryMsg::FirstQuery {} => to_json_binary("first query passed"), 62 | QueryMsg::SecondQuery { .. } => Err(StdError::generic_err("Query not available")), 63 | } 64 | } 65 | 66 | pub fn migrate(_deps: DepsMut, _env: Env, msg: MigrateMsg) -> StdResult> { 67 | if msg.t.eq("success") { 68 | Ok(Response::new()) 69 | } else { 70 | Err(StdError::generic_err( 71 | "migrate endpoint reached but no test implementation", 72 | )) 73 | } 74 | } 75 | 76 | #[cw_orch::interface(InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg)] 77 | struct MockContract; 78 | -------------------------------------------------------------------------------- /contracts-ws/contracts/mock_contract_u64/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "Mock constract for cw-orch macro testing" 3 | edition = { workspace = true } 4 | keywords = ["cosmwasm", "blockchain"] 5 | name = "mock-contract-u64" 6 | version = "0.1.0" 7 | 8 | exclude = [".env"] 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [features] 14 | default = ["export"] 15 | export = [] 16 | 17 | [dependencies] 18 | cosmwasm-schema = "2.1" 19 | cosmwasm-std = { workspace = true } 20 | cw-orch = { workspace = true } 21 | schemars = "0.8.21" 22 | serde = { workspace = true } 23 | serde_json = "1.0.125" 24 | thiserror = { version = "1.0.63" } 25 | 26 | mock-contract = { path = "../mock_contract" } 27 | -------------------------------------------------------------------------------- /contracts-ws/contracts/mock_contract_u64/README.md: -------------------------------------------------------------------------------- 1 | # Mock Contract test 2 | 3 | This folder is used for testing. 4 | -------------------------------------------------------------------------------- /cw-orch-daemon/README.md: -------------------------------------------------------------------------------- 1 | # Cosmwasm Orchestrator Daemon 2 | This library implements types Daemon and DaemonAsync for Synchronous and Asynchronous chain communications 3 | 4 | See [top-level README](../README.md) -------------------------------------------------------------------------------- /cw-orch-daemon/examples/batch-sender.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::{ 2 | msg::InstantiateMsg, CounterContract, CounterExecuteMsgFns, CounterQueryMsgFns, 3 | }; 4 | use cw_orch::{anyhow, daemon::senders::BatchDaemon, prelude::*}; 5 | use cw_orch_daemon::senders::CosmosBatchOptions; 6 | 7 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L2 8 | const LOCAL_MNEMONIC: &str = "clip hire initial neck maid actor venue client foam budget lock catalog sweet steak waste crater broccoli pipe steak sister coyote moment obvious choose"; 9 | pub fn main() -> anyhow::Result<()> { 10 | std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC); 11 | dotenv::dotenv().ok(); // Used to load the `.env` file if any 12 | pretty_env_logger::init(); // Used to log contract and chain interactions 13 | 14 | let network = networks::LOCAL_JUNO; 15 | let chain: BatchDaemon = 16 | BatchDaemon::builder(network).build_sender(CosmosBatchOptions::default())?; 17 | 18 | let counter = CounterContract::new(chain.clone()); 19 | 20 | counter.upload()?; 21 | counter.instantiate(&InstantiateMsg { count: 0 }, None, &[])?; 22 | 23 | counter.increment()?; 24 | 25 | // The count hasn't been incremented yet, we didn't broadcast the tx 26 | let count = counter.get_count()?; 27 | assert_eq!(count.count, 0); 28 | 29 | chain.rt_handle.block_on(chain.sender().broadcast(None))?; 30 | 31 | let count = counter.get_count()?; 32 | assert_eq!(count.count, 1); 33 | 34 | // Increment multiple times in the same transaction 35 | counter.increment()?; 36 | counter.increment()?; 37 | counter.increment()?; 38 | counter.increment()?; 39 | counter.increment()?; 40 | counter.increment()?; 41 | 42 | chain.rt_handle.block_on(chain.sender().broadcast(None))?; 43 | 44 | let count = counter.get_count()?; 45 | assert_eq!(count.count, 7); 46 | 47 | Ok(()) 48 | } 49 | -------------------------------------------------------------------------------- /cw-orch-daemon/examples/hd_index.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::coins; 2 | use cw_orch::{anyhow, prelude::*}; 3 | use cw_orch_daemon::CosmosOptions; 4 | 5 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L1 6 | pub const LOCAL_JUNO_SENDER: &str = "juno16g2rahf5846rxzp3fwlswy08fz8ccuwk03k57y"; 7 | pub const LOCAL_JUNO_GRANTER: &str = "juno1afhtjur8js4589xymu346ca7a5y5293xpuv6ry"; 8 | 9 | pub fn main() -> anyhow::Result<()> { 10 | pretty_env_logger::init(); // Used to log contract and chain interactions 11 | 12 | let network = networks::LOCAL_JUNO; 13 | // The mnemonic is read from environment variables automatically, no need to specify in this builders 14 | let sender = CosmosOptions::default() 15 | .hd_index(5) 16 | .authz_granter(&Addr::unchecked(LOCAL_JUNO_GRANTER)); 17 | let chain = Daemon::builder(network).build_sender(sender)?; 18 | 19 | chain.bank_send(&Addr::unchecked(LOCAL_JUNO_GRANTER), &coins(10000, "ujuno"))?; 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /cw-orch-daemon/examples/querier-daemon.rs: -------------------------------------------------------------------------------- 1 | // ANCHOR: full_counter_example 2 | 3 | use cw_orch::{anyhow, prelude::*}; 4 | use cw_orch_daemon::senders::QueryOnlyDaemon; 5 | 6 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L1 7 | pub const LOCAL_JUNO_SENDER: &str = "juno16g2rahf5846rxzp3fwlswy08fz8ccuwk03k57y"; 8 | 9 | pub fn main() -> anyhow::Result<()> { 10 | pretty_env_logger::init(); // Used to log contract and chain interactions 11 | 12 | let network = networks::LOCAL_JUNO; 13 | // QueryOnlyDaemon doesn't need a mnemonic to function 14 | let chain: QueryOnlyDaemon = QueryOnlyDaemon::builder(network).build_sender(())?; 15 | 16 | let balances = chain 17 | .bank_querier() 18 | .balance(&Addr::unchecked(LOCAL_JUNO_SENDER), None)?; 19 | assert!(!balances.is_empty()); 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/keys/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | pub mod private; 3 | pub mod public; 4 | pub mod signature; 5 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/keys/signature.rs: -------------------------------------------------------------------------------- 1 | use crate::DaemonError; 2 | use base64::engine::{general_purpose::STANDARD, Engine}; 3 | use bitcoin::secp256k1::{Message, Secp256k1}; 4 | use ring::digest::SHA256; 5 | pub struct Signature {} 6 | impl Signature { 7 | pub fn verify( 8 | secp: &Secp256k1, 9 | pub_key: &str, 10 | signature: &str, 11 | blob: &str, 12 | ) -> Result<(), DaemonError> { 13 | let public = STANDARD.decode(pub_key)?; 14 | let sig = STANDARD.decode(signature)?; 15 | let pk = bitcoin::secp256k1::PublicKey::from_slice(public.as_slice())?; 16 | let sha_result = ring::digest::digest(&SHA256, blob.as_bytes()); 17 | let message: Message = Message::from_digest_slice(&sha_result.as_ref()[0..32])?; 18 | let secp_sig = bitcoin::secp256k1::ecdsa::Signature::from_compact(sig.as_slice())?; 19 | secp.verify_ecdsa(&message, &secp_sig, &pk)?; 20 | Ok(()) 21 | } 22 | } 23 | #[cfg(test)] 24 | mod tst { 25 | use super::*; 26 | #[test] 27 | pub fn test_verify() -> anyhow::Result<()> { 28 | let secp = Secp256k1::new(); 29 | 30 | let message = r#"{"account_number":"45","chain_id":"columbus-3-testnet","fee":{"amount":[{"amount":"698","denom":"uluna"}],"gas":"46467"},"memo":"","msgs":[{"type":"bank/MsgSend","value":{"amount":[{"amount":"100000000","denom":"uluna"}],"from_address":"terra1n3g37dsdlv7ryqftlkef8mhgqj4ny7p8v78lg7","to_address":"terra1wg2mlrxdmnnkkykgqg4znky86nyrtc45q336yv"}}],"sequence":"0"}"#; 31 | let signature = "FJKAXRxNB5ruqukhVqZf3S/muZEUmZD10fVmWycdVIxVWiCXXFsUy2VY2jINEOUGNwfrqEZsT2dUfAvWj8obLg=="; 32 | let pub_key = "AiMzHaA2bvnDXfHzkjMM+vkSE/p0ymBtAFKUnUtQAeXe"; 33 | Signature::verify(&secp, pub_key, signature, message)?; 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/lib.rs: -------------------------------------------------------------------------------- 1 | // TODO: Figure out better mutex locking for senders 2 | #![allow(clippy::await_holding_lock)] 3 | //! `Daemon` and `DaemonAsync` execution environments. 4 | //! 5 | //! The `Daemon` type is a synchronous wrapper around the `DaemonAsync` type and can be used as a contract execution environment. 6 | pub mod json_lock; 7 | /// Proto types for different blockchains 8 | pub mod proto; 9 | // expose these as mods as they can grow 10 | pub mod env; 11 | pub mod keys; 12 | pub mod live_mock; 13 | pub mod queriers; 14 | pub mod senders; 15 | pub mod tx_broadcaster; 16 | pub mod tx_builder; 17 | 18 | mod builder; 19 | mod channel; 20 | mod core; 21 | mod error; 22 | mod log; 23 | mod network_config; 24 | mod state; 25 | mod sync; 26 | mod tx_resp; 27 | 28 | pub use self::{builder::*, channel::*, core::*, error::*, state::*, sync::*, tx_resp::*}; 29 | pub use cw_orch_networks::networks; 30 | pub use network_config::read_network_config; 31 | pub use senders::{query::QuerySender, tx::TxSender, CosmosOptions, Wallet}; 32 | pub use tx_builder::TxBuilder; 33 | 34 | pub(crate) mod cosmos_modules { 35 | pub use cosmrs::proto::{ 36 | cosmos::{ 37 | auth::v1beta1 as auth, 38 | authz::v1beta1 as authz, 39 | bank::v1beta1 as bank, 40 | base::{abci::v1beta1 as abci, tendermint::v1beta1 as tendermint}, 41 | feegrant::v1beta1 as feegrant, 42 | gov::v1beta1 as gov, 43 | staking::v1beta1 as staking, 44 | tx::v1beta1 as tx, 45 | vesting::v1beta1 as vesting, 46 | }, 47 | cosmwasm::wasm::v1 as cosmwasm, 48 | ibc::{ 49 | applications::transfer::v1 as ibc_transfer, 50 | core::{ 51 | channel::v1 as ibc_channel, client::v1 as ibc_client, 52 | connection::v1 as ibc_connection, 53 | }, 54 | }, 55 | tendermint::v0_34::abci as tendermint_abci, 56 | }; 57 | } 58 | 59 | lazy_static::lazy_static! { 60 | pub static ref RUNTIME: tokio::runtime::Runtime = tokio::runtime::Runtime::new().unwrap(); 61 | } 62 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/log.rs: -------------------------------------------------------------------------------- 1 | use crate::env::DaemonEnvVars; 2 | 3 | use crate::DaemonError; 4 | 5 | use std::sync::Once; 6 | 7 | static LOGS_DISABLED: Once = Once::new(); 8 | 9 | // Prints a warning if log is disabled for the application 10 | pub fn print_if_log_disabled() -> Result<(), DaemonError> { 11 | LOGS_DISABLED.call_once(|| { 12 | // Here we check for logging capabilities. 13 | if !log::log_enabled!(log::Level::Info) && DaemonEnvVars::logs_message() { 14 | println!( 15 | "Warning: It seems like you haven't enabled logs. In order to do so, you have to : 16 | - use `env_logger::init()` at the start of your script. 17 | - Set the env variable `RUST_LOG=info` for standard logs. See https://docs.rs/env_logger/latest/env_logger/" 18 | ) 19 | } 20 | }); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/proto/injective.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | use crate::DaemonError; 4 | use cosmrs::tx::Raw; 5 | use cosmrs::tx::SignDoc; 6 | use prost::Name; 7 | 8 | #[cfg(feature = "eth")] 9 | use crate::keys::private::PrivateKey; 10 | 11 | #[cfg(feature = "eth")] 12 | use ::{cosmrs::proto, ethers_core::utils::keccak256}; 13 | 14 | pub const ETHEREUM_COIN_TYPE: u32 = 60; 15 | 16 | #[derive(Clone, PartialEq, ::prost::Message)] 17 | pub struct InjectiveEthAccount { 18 | #[prost(message, optional, tag = "1")] 19 | pub base_account: ::core::option::Option, 20 | #[prost(bytes, tag = "2")] 21 | pub code_hash: Vec, 22 | } 23 | 24 | #[derive(Clone, PartialEq, ::prost::Message)] 25 | pub struct InjectivePubKey { 26 | #[prost(bytes, tag = 1)] 27 | pub key: Vec, 28 | } 29 | 30 | impl Name for InjectivePubKey { 31 | const NAME: &'static str = "PubKey"; 32 | const PACKAGE: &'static str = "/injective.crypto.v1beta1.ethsecp256k1"; 33 | 34 | /// Workaround until tokio-rs/prost#923 is released 35 | fn full_name() -> String { 36 | format!("{}.{}", Self::PACKAGE, Self::NAME) 37 | } 38 | } 39 | 40 | pub trait InjectiveSigner { 41 | fn sign_injective(&self, sign_doc: SignDoc) -> Result; 42 | } 43 | 44 | #[cfg(feature = "eth")] 45 | impl InjectiveSigner for PrivateKey { 46 | fn sign_injective(&self, sign_doc: SignDoc) -> Result { 47 | let sign_doc_bytes = sign_doc.clone().into_bytes()?; 48 | 49 | // sign with ethers 50 | 51 | let msg_hash = keccak256(sign_doc_bytes); 52 | let eth_signature = ethers_signers::Wallet::from_bytes(&self.raw_key()) 53 | .unwrap() 54 | .sign_hash(msg_hash.into()) 55 | .unwrap(); 56 | 57 | let tx_raw: Raw = proto::cosmos::tx::v1beta1::TxRaw { 58 | body_bytes: sign_doc.body_bytes, 59 | auth_info_bytes: sign_doc.auth_info_bytes, 60 | signatures: vec![eth_signature.to_vec()], 61 | } 62 | .into(); 63 | 64 | Ok(tx_raw) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/proto/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod injective; 2 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/queriers/env.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{EnvironmentInfo, EnvironmentQuerier}; 2 | 3 | use crate::{senders::query::QuerySender, DaemonBase}; 4 | 5 | impl EnvironmentQuerier for DaemonBase { 6 | fn env_info(&self) -> EnvironmentInfo { 7 | let info = self.daemon.chain_info(); 8 | EnvironmentInfo { 9 | chain_id: info.chain_id.clone(), 10 | chain_name: info.network_info.chain_name.clone(), 11 | deployment_id: self.daemon.state.deployment_id.clone(), 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/senders/builder.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use cw_orch_core::environment::ChainInfoOwned; 4 | 5 | use crate::DaemonError; 6 | 7 | /// Allows building a `Sender` from `SenderBuilder::Options` 8 | /// `async`` because it could do network requests during build 9 | pub trait SenderBuilder { 10 | type Error: Into + std::error::Error + std::fmt::Debug + Send + Sync + 'static; 11 | type Sender; 12 | 13 | /// Build a new `Sender`. 14 | fn build( 15 | &self, 16 | chain_info: &Arc, 17 | ) -> impl std::future::Future> + Send; 18 | } 19 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/senders/mod.rs: -------------------------------------------------------------------------------- 1 | // Core Sender traits 2 | pub mod builder; 3 | pub mod query; 4 | pub mod sign; 5 | pub mod tx; 6 | 7 | // Senders 8 | mod cosmos; 9 | mod cosmos_batch; 10 | mod cosmos_options; 11 | mod query_only; 12 | 13 | pub use { 14 | cosmos::{CosmosSender, Wallet}, 15 | cosmos_batch::{options::CosmosBatchOptions, BatchDaemon, CosmosBatchSender}, 16 | cosmos_options::{CosmosOptions, CosmosWalletKey}, 17 | query_only::{QueryOnlyDaemon, QueryOnlySender}, 18 | }; 19 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/senders/query.rs: -------------------------------------------------------------------------------- 1 | use tonic::transport::Channel; 2 | 3 | use crate::DaemonError; 4 | 5 | use super::builder::SenderBuilder; 6 | 7 | /// A sender that can query information over a connection. 8 | pub trait QuerySender: Clone { 9 | type Error: Into + std::error::Error + std::fmt::Debug + Send + Sync + 'static; 10 | /// Options for this sender 11 | type Options: SenderBuilder; 12 | 13 | /// Get the channel for the sender 14 | fn channel(&self) -> Channel; 15 | } 16 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/senders/query_only.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::{error::DaemonError, DaemonBase, GrpcChannel}; 4 | 5 | use cw_orch_core::environment::ChainInfoOwned; 6 | 7 | use tonic::transport::Channel; 8 | 9 | use super::{builder::SenderBuilder, query::QuerySender}; 10 | 11 | /// Daemon that does not support signing. 12 | /// Will err on any attempt to sign a transaction or retrieve a sender address. 13 | pub type QueryOnlyDaemon = DaemonBase; 14 | 15 | /// Signer of the transactions and helper for address derivation 16 | #[derive(Clone)] 17 | pub struct QueryOnlySender { 18 | /// gRPC channel 19 | pub channel: Channel, 20 | /// Information about the chain 21 | pub chain_info: Arc, 22 | } 23 | 24 | impl SenderBuilder for () { 25 | type Error = DaemonError; 26 | type Sender = QueryOnlySender; 27 | 28 | async fn build(&self, chain_info: &Arc) -> Result { 29 | let channel = GrpcChannel::from_chain_info(chain_info.as_ref()).await?; 30 | 31 | Ok(QueryOnlySender { 32 | channel, 33 | chain_info: chain_info.clone(), 34 | }) 35 | } 36 | } 37 | 38 | impl QuerySender for QueryOnlySender { 39 | type Error = DaemonError; 40 | type Options = (); 41 | 42 | fn channel(&self) -> Channel { 43 | self.channel.clone() 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use cw_orch_networks::networks::{ARCHWAY_1, JUNO_1}; 50 | 51 | use super::QueryOnlyDaemon; 52 | use crate::DaemonBuilder; 53 | 54 | #[test] 55 | #[serial_test::serial] 56 | fn build() { 57 | let _query_only_daemon: QueryOnlyDaemon = 58 | DaemonBuilder::new(JUNO_1).build_sender(()).unwrap(); 59 | } 60 | 61 | #[test] 62 | #[serial_test::serial] 63 | fn tls_grpc() { 64 | let chain = ARCHWAY_1; 65 | // Make sure this test is up to date 66 | assert!(chain.grpc_urls[0].starts_with("https")); 67 | let _query_only_daemon: QueryOnlyDaemon = 68 | DaemonBuilder::new(chain).build_sender(()).unwrap(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cw-orch-daemon/src/sync/mod.rs: -------------------------------------------------------------------------------- 1 | mod builder; 2 | mod core; 3 | 4 | pub use self::{builder::*, core::*}; 5 | -------------------------------------------------------------------------------- /cw-orch-daemon/tests/index.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | #[cfg(feature = "node-tests")] 3 | mod tests { 4 | 5 | use cw_orch_core::environment::TxHandler; 6 | use cw_orch_daemon::{senders::CosmosOptions, Daemon}; 7 | 8 | #[test] 9 | #[serial_test::serial] 10 | fn mnemonic_index() -> anyhow::Result<()> { 11 | use cw_orch_networks::networks; 12 | super::common::enable_logger(); 13 | 14 | let daemon = Daemon::builder(networks::LOCAL_JUNO) 15 | .is_test(true) 16 | .build() 17 | .unwrap(); 18 | 19 | let daemon_sender = daemon.sender_addr().to_string(); 20 | let indexed_daemon: Daemon = daemon 21 | .rebuild() 22 | .build_sender(CosmosOptions::default().hd_index(56)) 23 | .unwrap(); 24 | 25 | assert_ne!(daemon_sender, indexed_daemon.sender_addr().to_string()); 26 | 27 | Ok(()) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cw-orch-daemon/tests/instantiate2.rs: -------------------------------------------------------------------------------- 1 | mod common; 2 | 3 | #[cfg(feature = "node-tests")] 4 | pub mod test { 5 | 6 | use cosmwasm_std::Binary; 7 | use cw_orch_core::contract::interface_traits::ContractInstance; 8 | use cw_orch_core::contract::interface_traits::CwOrchInstantiate; 9 | use cw_orch_core::contract::interface_traits::CwOrchUpload; 10 | use cw_orch_daemon::Daemon; 11 | use cw_orch_networks::networks; 12 | use mock_contract::InstantiateMsg; 13 | use mock_contract::MockContract; 14 | 15 | #[test] 16 | #[serial_test::serial] 17 | fn instantiate2() -> anyhow::Result<()> { 18 | super::common::enable_logger(); 19 | let app = Daemon::builder(networks::LOCAL_JUNO) 20 | .is_test(true) 21 | .build() 22 | .unwrap(); 23 | 24 | let salt = Binary::new(vec![12, 89, 156, 63]); 25 | let mock_contract = MockContract::new("mock-contract", app.clone()); 26 | 27 | mock_contract.upload()?; 28 | 29 | mock_contract.instantiate2(&InstantiateMsg {}, None, &[], salt.clone())?; 30 | 31 | mock_contract.address()?; 32 | 33 | Ok(()) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cw-orch-daemon/tests/mock_networks.toml: -------------------------------------------------------------------------------- 1 | [juno-1] 2 | chain_id = "joono-1" 3 | fcd_url = "http://juno-fcd.com:234" 4 | gas_denom = "gas_denom" 5 | gas_price = 64 6 | grpc_urls = ["http://juno-grpc.com:123"] 7 | kind = "local" 8 | lcd_url = "http://juno-lcd.com:321" 9 | network_info = { chain_name = "joono", pub_address_prefix = "joo", coin_type = 42 } 10 | 11 | [neutron-1] 12 | gas_price = 1.23 13 | 14 | [abstr-1] 15 | chain_id = "juno-1" 16 | gas_denom = "ujuno" 17 | gas_price = 0.075 18 | grpc_urls = ["http://juno-grpc.polkachu.com:12690"] 19 | kind = "mainnet" 20 | network_info = { chain_name = "juno", pub_address_prefix = "juno", coin_type = 118 } 21 | -------------------------------------------------------------------------------- /cw-orch-interchain/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | categories = ["development-tools"] 4 | description = "Scripting library for deploying and interacting with CosmWasm smart-contracts" 5 | edition = { workspace = true } 6 | keywords = ["cosmwasm", "blockchain"] 7 | license = { workspace = true } 8 | name = "cw-orch-interchain" 9 | repository = { workspace = true } 10 | version = "0.8.1" 11 | 12 | exclude = [".env"] 13 | 14 | [package.metadata.docs.rs] 15 | # passes all-features to cargo when building the docs. 16 | all-features = true 17 | 18 | [features] 19 | default = [] 20 | # enable the optional dependencies 21 | daemon = ["cw-orch-interchain-core/daemon", "dep:cw-orch-interchain-daemon", "dep:cw-orch-starship"] 22 | 23 | 24 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 25 | 26 | cw-orch-interchain-core = { workspace = true } 27 | cw-orch-interchain-daemon = { workspace = true, optional = true } 28 | cw-orch-interchain-mock = { workspace = true } 29 | cw-orch-starship = { workspace = true, optional = true } 30 | ibc-relayer-types.workspace = true 31 | 32 | #Used only for testing 33 | cosmwasm-std.workspace = true 34 | cw1 = "2.0.0" 35 | cw1-whitelist = "2.0.0" 36 | speculoos.workspace = true 37 | 38 | [dev-dependencies] 39 | clap = { version = "4.5.16", features = ["derive"] } 40 | cosmos-sdk-proto = { workspace = true } 41 | cw-orch = { workspace = true, features = ["daemon"] } 42 | cw-orch-interchain = { path = ".", features = ["daemon"] } 43 | dotenv = "0.15.0" 44 | env_logger = "0.11.5" 45 | ibc-proto = { workspace = true } 46 | ibc-relayer-types.workspace = true 47 | log.workspace = true 48 | pretty_env_logger = "0.5.0" 49 | prost-types = { workspace = true } 50 | simple-ica-controller = { git = "https://github.com/Buckram123/cw-ibc-demo.git", rev = "2cc3c14" } 51 | simple-ica-host = { git = "https://github.com/Buckram123/cw-ibc-demo.git", rev = "2cc3c14" } 52 | speculoos.workspace = true 53 | tokio = "1.39.2" 54 | -------------------------------------------------------------------------------- /cw-orch-interchain/examples/doc_daemon.rs: -------------------------------------------------------------------------------- 1 | use cw_orch::prelude::networks::{LOCAL_JUNO, LOCAL_MIGALOO, LOCAL_OSMO}; 2 | use cw_orch::prelude::*; 3 | use cw_orch_interchain::prelude::*; 4 | 5 | fn create_daemon_env() -> cw_orch::anyhow::Result { 6 | // ANCHOR: DAEMON_INTERCHAIN_CREATION 7 | // This will create `Daemon` structures associated with chains `LOCAL_JUNO` and `LOCAL_OSMO` 8 | let mut interchain = 9 | DaemonInterchain::new(vec![LOCAL_JUNO, LOCAL_OSMO], &ChannelCreationValidator)?; 10 | 11 | let local_juno: Daemon = interchain.get_chain("testing")?; 12 | let _local_osmo: Daemon = interchain.get_chain("localosmosis")?; 13 | 14 | // You can also create your own daemon and add it manually 15 | let local_migaloo = DaemonBuilder::new(LOCAL_MIGALOO) 16 | .state(local_juno.state()) 17 | .build()?; 18 | 19 | interchain.add_daemons(vec![local_migaloo]); 20 | // ANCHOR_END: DAEMON_INTERCHAIN_CREATION 21 | Ok(interchain) 22 | } 23 | 24 | fn create_starship_env() -> cw_orch::anyhow::Result> { 25 | // ANCHOR: STARSHIP_INTERCHAIN_CREATION 26 | let starship = Starship::new(None)?; 27 | let interchain = starship.interchain_env(); 28 | 29 | let _local_juno: Daemon = interchain.get_chain("juno-1")?; 30 | let _local_osmo: Daemon = interchain.get_chain("osmosis-1")?; 31 | // ANCHOR_END: STARSHIP_INTERCHAIN_CREATION 32 | 33 | Ok(interchain) 34 | } 35 | 36 | fn test() -> cw_orch::anyhow::Result<()> { 37 | create_daemon_env()?; 38 | create_starship_env()?; 39 | Ok(()) 40 | } 41 | 42 | fn main() { 43 | test().unwrap(); 44 | } 45 | -------------------------------------------------------------------------------- /cw-orch-interchain/examples/doc_mock.rs: -------------------------------------------------------------------------------- 1 | use cw_orch::prelude::*; 2 | use cw_orch_interchain::prelude::*; 3 | use ibc_relayer_types::core::ics24_host::identifier::PortId; 4 | 5 | fn crate_mock_env() -> cw_orch::anyhow::Result { 6 | let sender = "sender"; 7 | let mut interchain = MockInterchainEnv::new(vec![("juno-1", sender), ("osmosis-1", sender)]); 8 | 9 | let _test_juno: Mock = interchain.get_chain("juno-1")?; 10 | let _test_osmo: Mock = interchain.get_chain("osmosis-1")?; 11 | 12 | let test_migaloo = Mock::new(sender); 13 | interchain.add_mocks(vec![test_migaloo]); 14 | 15 | Ok(interchain) 16 | } 17 | 18 | fn create_channel(interchain: MockInterchainEnv) -> cw_orch::anyhow::Result<()> { 19 | let src_chain = "juno-1".to_string(); 20 | let dst_chain = "osmosis-1".to_string(); 21 | let port_id = PortId::transfer(); 22 | interchain.create_channel( 23 | &src_chain, 24 | &dst_chain, 25 | &port_id, 26 | &port_id, 27 | "ics20-1", 28 | Some(cosmwasm_std::IbcOrder::Unordered), 29 | )?; 30 | Ok(()) 31 | } 32 | 33 | fn test() -> cw_orch::anyhow::Result<()> { 34 | let interchain = crate_mock_env()?; 35 | create_channel(interchain)?; 36 | Ok(()) 37 | } 38 | 39 | fn main() { 40 | test().unwrap(); 41 | } 42 | -------------------------------------------------------------------------------- /cw-orch-interchain/examples/follow_packets_txhash.rs: -------------------------------------------------------------------------------- 1 | use cw_orch::{ 2 | daemon::networks::ARCHWAY_1, 3 | environment::{ChainInfo, NetworkInfo}, 4 | prelude::networks::osmosis::OSMOSIS_1, 5 | }; 6 | use cw_orch_interchain::prelude::*; 7 | 8 | pub const NOBLE: NetworkInfo = NetworkInfo { 9 | chain_name: "noble", 10 | pub_address_prefix: "noble", 11 | coin_type: 118, 12 | }; 13 | pub const NOBLE_1: ChainInfo = ChainInfo { 14 | chain_id: "noble-1", 15 | gas_denom: "uusdc", 16 | gas_price: 0.1, 17 | grpc_urls: &["http://noble-grpc.polkachu.com:21590"], 18 | lcd_url: None, 19 | fcd_url: None, 20 | network_info: NOBLE, 21 | kind: cw_orch::environment::ChainKind::Mainnet, 22 | }; 23 | 24 | fn follow_by_tx_hash() -> cw_orch::anyhow::Result<()> { 25 | dotenv::dotenv()?; 26 | 27 | let dst_chain = ARCHWAY_1; 28 | let src_chain = OSMOSIS_1; 29 | 30 | let interchain = DaemonInterchain::new( 31 | vec![src_chain.clone(), dst_chain], 32 | &ChannelCreationValidator, 33 | )?; 34 | 35 | interchain 36 | .await_packets_for_txhash( 37 | src_chain.chain_id, 38 | "D2C5459C54B394C168B8DFA214670FF9E2A0349CCBEF149CF5CB508A5B3BCB84".to_string(), 39 | )? 40 | .assert()?; 41 | 42 | Ok(()) 43 | } 44 | 45 | fn main() { 46 | env_logger::init(); 47 | follow_by_tx_hash().unwrap(); 48 | } 49 | -------------------------------------------------------------------------------- /cw-orch-interchain/examples/manual_ica_demo.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_interchain::prelude::*; 2 | 3 | // Integrating the test inside the example 4 | mod common { 5 | include!("../tests/common/mod.rs"); 6 | } 7 | 8 | pub const JUNO: &str = "juno-1"; 9 | pub const STARGAZE: &str = "stargaze-1"; 10 | pub const JUNO_FUNDS_DENOM: &str = "ujuno"; 11 | 12 | fn main() { 13 | dotenv().ok(); 14 | use dotenv::dotenv; 15 | env_logger::init(); 16 | 17 | // Depending on binary arguments, we se starship or a rpc based solution (with manual channel creation) 18 | 19 | let starship = Starship::new(None).unwrap(); 20 | 21 | let interchain = DaemonInterchain::from_daemons( 22 | starship.daemons.values().cloned().collect(), 23 | &ChannelCreationValidator, 24 | ); 25 | common::ica_demo::full_ica_test(&interchain, JUNO, STARGAZE, JUNO_FUNDS_DENOM).unwrap(); 26 | } 27 | -------------------------------------------------------------------------------- /cw-orch-interchain/examples/starship_ica_demo.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_interchain::prelude::*; 2 | 3 | // Integrating the test inside the example 4 | mod common { 5 | include!("../tests/common/mod.rs"); 6 | } 7 | 8 | pub const JUNO: &str = "juno-1"; 9 | pub const STARGAZE: &str = "stargaze-1"; 10 | pub const JUNO_FUNDS_DENOM: &str = "ujuno"; 11 | 12 | fn main() { 13 | dotenv().ok(); 14 | use dotenv::dotenv; 15 | env_logger::init(); 16 | 17 | // We use starship to create channels 18 | let starship = Starship::new(None).unwrap(); 19 | let interchain = starship.interchain_env(); 20 | 21 | common::ica_demo::full_ica_test(&interchain, JUNO, STARGAZE, JUNO_FUNDS_DENOM).unwrap(); 22 | } 23 | -------------------------------------------------------------------------------- /cw-orch-interchain/src/lib.rs: -------------------------------------------------------------------------------- 1 | // prelude 2 | #[cfg(not(target_arch = "wasm32"))] 3 | pub mod prelude { 4 | pub use cw_orch_interchain_core::{ 5 | results::ChannelCreationResult, IbcPacketOutcome, IbcPacketResult, IbcQueryHandler, 6 | InterchainEnv, InterchainError, NestedPacketsFlow, PacketAnalysis, SinglePacketFlow, 7 | SuccessNestedPacketsFlow, SuccessSinglePacketFlow, TxId, 8 | }; 9 | pub use cw_orch_interchain_mock::{MockBech32InterchainEnv, MockInterchainEnv}; 10 | 11 | pub use ibc_relayer_types::core::{ 12 | ics04_channel::packet::Sequence, 13 | ics24_host::identifier::{ChannelId, PortId}, 14 | }; 15 | 16 | #[cfg(feature = "daemon")] 17 | pub use cw_orch_interchain_daemon::{ 18 | ChannelCreationValidator, ChannelCreator, DaemonInterchain, 19 | }; 20 | #[cfg(feature = "daemon")] 21 | pub use cw_orch_starship::Starship; 22 | } 23 | 24 | #[cfg(not(target_arch = "wasm32"))] 25 | pub mod core { 26 | pub use cw_orch_interchain_core::*; 27 | } 28 | 29 | #[cfg(not(target_arch = "wasm32"))] 30 | pub mod mock { 31 | pub use cw_orch_interchain_mock::*; 32 | } 33 | 34 | #[cfg(not(target_arch = "wasm32"))] 35 | #[cfg(feature = "daemon")] 36 | pub mod daemon { 37 | pub use cw_orch_interchain_daemon::*; 38 | } 39 | 40 | #[cfg(not(target_arch = "wasm32"))] 41 | #[cfg(feature = "daemon")] 42 | pub mod starship { 43 | pub use cw_orch_starship::*; 44 | } 45 | -------------------------------------------------------------------------------- /cw-orch-interchain/tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ica_demo; 2 | -------------------------------------------------------------------------------- /cw-orch-interchain/tests/mock_ica_demo.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_interchain_core::InterchainEnv; 2 | use cw_orch_interchain_mock::MockInterchainEnv; 3 | mod common; 4 | use cosmwasm_std::coins; 5 | use cw_orch::prelude::*; 6 | 7 | pub fn logger_test_init() { 8 | let _ = env_logger::builder().is_test(true).try_init(); 9 | } 10 | 11 | pub const JUNO: &str = "juno-1"; 12 | pub const OSMOSIS: &str = "osmosis-1"; 13 | pub const JUNO_FUNDS_DENOM: &str = "ujuno"; 14 | 15 | #[test] 16 | fn mock_ica_demo() -> cw_orch::anyhow::Result<()> { 17 | // logger_test_init(); 18 | env_logger::init(); 19 | let common_sender = "sender"; 20 | let interchain = MockInterchainEnv::new(vec![(JUNO, common_sender), (OSMOSIS, common_sender)]); 21 | 22 | let juno = interchain.get_chain(JUNO)?; 23 | // We need to add balance to the JUNO chain 24 | juno.add_balance(&juno.sender_addr(), coins(100_000, JUNO_FUNDS_DENOM))?; 25 | 26 | common::ica_demo::full_ica_test(&interchain, JUNO, OSMOSIS, JUNO_FUNDS_DENOM)?; 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /cw-orch-interchain/tests/mock_transfer.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::{coin, CosmosMsg, IbcMsg, IbcTimeout, IbcTimeoutBlock}; 2 | use cw_orch::{ 3 | environment::{QueryHandler, TxHandler}, 4 | mock::cw_multi_test::Executor, 5 | }; 6 | use cw_orch_interchain_core::InterchainEnv; 7 | use cw_orch_interchain_mock::MockInterchainEnv; 8 | use ibc_relayer_types::core::ics24_host::identifier::PortId; 9 | 10 | #[test] 11 | fn mock_transfer() -> cw_orch::anyhow::Result<()> { 12 | pretty_env_logger::init(); 13 | 14 | let interchain = MockInterchainEnv::new(vec![("juno-1", "sender"), ("stargaze-1", "sender")]); 15 | 16 | let channel = interchain 17 | .create_channel( 18 | "juno-1", 19 | "stargaze-1", 20 | &PortId::transfer(), 21 | &PortId::transfer(), 22 | "ics20-1", 23 | None, 24 | ) 25 | .unwrap(); 26 | let juno = interchain.get_chain("juno-1").unwrap(); 27 | let stargaze = interchain.get_chain("stargaze-1").unwrap(); 28 | 29 | let channel = channel 30 | .interchain_channel 31 | .get_ordered_ports_from("juno-1") 32 | .unwrap(); 33 | 34 | juno.add_balance(&juno.sender_addr(), vec![coin(100_000, "ujuno")]) 35 | .unwrap(); 36 | let tx_resp = juno 37 | .app 38 | .borrow_mut() 39 | .execute( 40 | juno.sender_addr(), 41 | CosmosMsg::Ibc(IbcMsg::Transfer { 42 | channel_id: channel.0.channel.unwrap().to_string(), 43 | to_address: stargaze.sender_addr().to_string(), 44 | amount: coin(100_000, "ujuno"), 45 | timeout: IbcTimeout::with_block(IbcTimeoutBlock { 46 | revision: 1, 47 | height: stargaze.block_info().unwrap().height + 1, 48 | }), 49 | memo: None, 50 | }), 51 | ) 52 | .unwrap(); 53 | 54 | // This makes sure that the packets arrive successfully and present a success ack 55 | interchain 56 | .await_and_check_packets("juno-1", tx_resp) 57 | .unwrap(); 58 | 59 | Ok(()) 60 | } 61 | -------------------------------------------------------------------------------- /cw-orch-interchain/tests/timeout_packet_mock.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::{coin, CosmosMsg, IbcMsg, IbcTimeout, IbcTimeoutBlock}; 2 | use cw_orch::{ 3 | environment::{QueryHandler, TxHandler}, 4 | mock::cw_multi_test::Executor, 5 | }; 6 | use cw_orch_interchain_core::InterchainEnv; 7 | use cw_orch_interchain_mock::MockInterchainEnv; 8 | use ibc_relayer_types::core::ics24_host::identifier::PortId; 9 | 10 | #[test] 11 | fn timeout_packet_mock() -> cw_orch::anyhow::Result<()> { 12 | pretty_env_logger::init(); 13 | 14 | let interchain = MockInterchainEnv::new(vec![("juno-1", "sender"), ("stargaze-1", "sender")]); 15 | 16 | let channel = interchain.create_channel( 17 | "juno-1", 18 | "stargaze-1", 19 | &PortId::transfer(), 20 | &PortId::transfer(), 21 | "ics20-1", 22 | None, 23 | )?; 24 | let juno = interchain.get_chain("juno-1")?; 25 | let stargaze = interchain.get_chain("stargaze-1")?; 26 | 27 | let stargaze_height = stargaze.block_info()?; 28 | let channel = channel 29 | .interchain_channel 30 | .get_ordered_ports_from("juno-1")?; 31 | 32 | juno.add_balance(&juno.sender_addr(), vec![coin(100_000, "ujuno")])?; 33 | let tx_resp = juno.app.borrow_mut().execute( 34 | juno.sender_addr(), 35 | CosmosMsg::Ibc(IbcMsg::Transfer { 36 | channel_id: channel.0.channel.unwrap().to_string(), 37 | to_address: stargaze.sender_addr().to_string(), 38 | amount: coin(100_000, "ujuno"), 39 | timeout: IbcTimeout::with_block(IbcTimeoutBlock { 40 | revision: 1, 41 | height: stargaze_height.height, 42 | }), 43 | memo: None, 44 | }), 45 | )?; 46 | 47 | let result = interchain.await_packets("juno-1", tx_resp)?; 48 | 49 | match &result.packets[0] { 50 | cw_orch_interchain_core::IbcPacketOutcome::Timeout { .. } => {} 51 | cw_orch_interchain_core::IbcPacketOutcome::Success { .. } => { 52 | panic!("Expected timeout") 53 | } 54 | } 55 | 56 | Ok(()) 57 | } 58 | -------------------------------------------------------------------------------- /cw-orch-interchain/wasms/cw1_whitelist.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/cw-orch-interchain/wasms/cw1_whitelist.wasm -------------------------------------------------------------------------------- /cw-orch-interchain/wasms/simple_ica_controller.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/cw-orch-interchain/wasms/simple_ica_controller.wasm -------------------------------------------------------------------------------- /cw-orch-interchain/wasms/simple_ica_host.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbstractSDK/cw-orchestrator/b53bab51a0ab1ed7d8292fdfda0b712ef067ef39/cw-orch-interchain/wasms/simple_ica_host.wasm -------------------------------------------------------------------------------- /cw-orch/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /cw-orch/examples/async_daemon.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::AsyncCounterQueryMsgFns; 2 | use counter_contract::CounterContract; 3 | 4 | use cw_orch_daemon::DaemonAsync; 5 | /// In order to use this script, you need to set the following env variables 6 | /// 7 | /// RUST_LOG (recommended value `info`) to see the app logs 8 | /// 9 | /// TEST_MNEMONIC to be able to sign and broadcast a transaction on UNI testnet 10 | #[tokio::main] 11 | pub async fn main() -> anyhow::Result<()> { 12 | // We start by loading environment variables from a .env file. 13 | // You can use a .env file to specify environment variables. 14 | // You have an overview of all supported environment variables here : https://orchestrator.abstract.money/contracts/env-variable.html 15 | dotenv::dotenv().unwrap(); 16 | 17 | // We initialize the env logger to be able to see what's happening during the script execution 18 | // Remember to set the `RUST_LOG` env variable to be able to see the execution 19 | env_logger::init(); 20 | 21 | // We can now create a daemon. This daemon will be used to interact with the chain. 22 | // In the background, the `build` function uses the `TEST_MNEMONIC` variable, don't forget to set it ! 23 | let daemon = DaemonAsync::builder(cw_orch::daemon::networks::UNI_6) // set the network to use 24 | .build() 25 | .await?; 26 | 27 | // Uploading a contract is very simple 28 | let counter = CounterContract::new(daemon.clone()); 29 | let upload_res = daemon.upload(&counter).await; 30 | assert!(upload_res.is_ok()); 31 | 32 | let count = counter.get_count_async().await?; 33 | assert_eq!(count.count, 1); 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /cw-orch/examples/injective.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::{ 2 | msg::{ExecuteMsg, GetCountResponse, InstantiateMsg, QueryMsg}, 3 | CounterContract, 4 | }; 5 | use cw_orch::{ 6 | environment::Environment, 7 | prelude::{ 8 | networks, CwOrchExecute, CwOrchInstantiate, CwOrchQuery, CwOrchUpload, Daemon, TxHandler, 9 | }, 10 | }; 11 | 12 | const TESTNET_MNEMONIC: &str = "across left ignore gold echo argue track joy hire release captain enforce hotel wide flash hotel brisk joke midnight duck spare drop chronic stool"; 13 | 14 | pub fn main() { 15 | // There are two types of daemon, sync and async. Sync daemons can be used is generic code. Async daemons can be used 16 | // in async code (e.g. tokio), which enables multi-threaded and non-blocking code. 17 | 18 | env_logger::init(); 19 | 20 | // We can now create a daemon. This daemon will be used to interact with the chain. 21 | let res = Daemon::builder(networks::INJECTIVE_888) // set the network to use 22 | .mnemonic(TESTNET_MNEMONIC) 23 | .build(); 24 | 25 | let Some(daemon) = res.as_ref().ok() else { 26 | panic!("Error: {}", res.err().unwrap()); 27 | }; 28 | 29 | let counter = CounterContract::new(daemon.clone()); 30 | 31 | let upload_res = counter.upload(); 32 | assert!(upload_res.is_ok()); 33 | 34 | let init_res = counter.instantiate( 35 | &InstantiateMsg { count: 0 }, 36 | Some(&counter.environment().sender_addr()), 37 | &[], 38 | ); 39 | assert!(init_res.is_ok()); 40 | 41 | let exec_res = counter.execute(&ExecuteMsg::Increment {}, &[]); 42 | assert!(exec_res.is_ok()); 43 | 44 | let query_res = counter.query::(&QueryMsg::GetCount {}); 45 | assert!(query_res.is_ok()); 46 | } 47 | -------------------------------------------------------------------------------- /cw-orch/examples/local_daemon.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::{ 2 | msg::InstantiateMsg, CounterContract, CounterExecuteMsgFns, CounterQueryMsgFns, 3 | }; 4 | use cw_orch::{environment::Environment, prelude::*}; 5 | 6 | // From https://github.com/CosmosContracts/juno/blob/32568dba828ff7783aea8cb5bb4b8b5832888255/docker/test-user.env#L2 7 | const LOCAL_MNEMONIC: &str = "clip hire initial neck maid actor venue client foam budget lock catalog sweet steak waste crater broccoli pipe steak sister coyote moment obvious choose"; 8 | 9 | pub fn main() { 10 | // There are two types of daemon, sync and async. Sync daemons can be used is generic code. Async daemons can be used 11 | // in async code (e.g. tokio), which enables multi-threaded and non-blocking code. 12 | std::env::set_var("LOCAL_MNEMONIC", LOCAL_MNEMONIC); 13 | env_logger::init(); 14 | 15 | // ANCHOR: daemon_creation 16 | 17 | // We start by creating a daemon. This daemon will be used to interact with the chain. 18 | let daemon = Daemon::builder(cw_orch::daemon::networks::LOCAL_JUNO) // chain parameter 19 | .build() 20 | .unwrap(); 21 | 22 | // ANCHOR_END: daemon_creation 23 | 24 | // ANCHOR: daemon_usage 25 | let counter = CounterContract::new(daemon.clone()); 26 | 27 | let upload_res = counter.upload(); 28 | assert!(upload_res.is_ok()); 29 | 30 | let init_res = counter.instantiate( 31 | &InstantiateMsg { count: 0 }, 32 | Some(&counter.environment().sender_addr()), 33 | &[], 34 | ); 35 | assert!(init_res.is_ok()); 36 | // ANCHOR_END: daemon_usage 37 | 38 | let exec_res = counter.increment(); 39 | assert!(exec_res.is_ok()); 40 | 41 | let query_res = counter.get_count(); 42 | assert!(query_res.is_ok()); 43 | } 44 | -------------------------------------------------------------------------------- /cw-orch/examples/mockbech32.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::{ 2 | msg::InstantiateMsg, CounterContract, CounterExecuteMsgFns, CounterQueryMsgFns, 3 | }; 4 | use cw_orch::prelude::*; 5 | 6 | /// This example shows how to create and use the cw-multi-test mock environment 7 | pub fn main() -> anyhow::Result<()> { 8 | env_logger::init(); 9 | 10 | let mock = MockBech32::new("osmosis-1"); 11 | 12 | let contract_counter = CounterContract::new(mock.clone()); 13 | 14 | contract_counter.upload()?; 15 | contract_counter.instantiate(&InstantiateMsg { count: 0 }, None, &[])?; 16 | contract_counter.increment()?; 17 | 18 | let query_res = contract_counter.get_count()?; 19 | assert_eq!(query_res.count, 1); 20 | 21 | let new_sender = mock.addr_make("new-sender"); 22 | contract_counter.call_as(&new_sender).increment()?; 23 | 24 | let query_res = contract_counter.get_count()?; 25 | assert_eq!(query_res.count, 2); 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /cw-orch/examples/queries/bank_query.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result as AnyResult; 2 | use cw_orch::daemon::Daemon; 3 | use cw_orch::prelude::BankQuerier; 4 | use cw_orch::prelude::QuerierGetter; 5 | use cw_orch::prelude::TxHandler; 6 | use cw_orch_daemon::queriers::Bank; 7 | pub fn main() { 8 | dotenv::dotenv().unwrap(); 9 | env_logger::init(); 10 | // We can now create a daemon. This daemon will be used to interact with the chain. 11 | let daemon = Daemon::builder(cw_orch::daemon::networks::LOCAL_JUNO) // chain parameter 12 | .build() 13 | .unwrap(); 14 | 15 | test_queries(&daemon).unwrap() 16 | } 17 | 18 | pub fn test_queries(daemon: &Daemon) -> AnyResult<()> { 19 | // ANCHOR: daemon_balance_query 20 | let bank_query_client: Bank = daemon.querier(); 21 | 22 | let sender = daemon.sender_addr(); 23 | let balance_result = bank_query_client.balance(&sender, None)?; 24 | println!("Balance of {} : {:?}", sender, balance_result); 25 | 26 | // ANCHOR_END: daemon_balance_query 27 | 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /cw-orch/examples/queries/testnet_queries.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result as AnyResult; 2 | use cosmwasm_std::Addr; 3 | use cw_orch::daemon::Daemon; 4 | use cw_orch::prelude::BankQuerier; 5 | use cw_orch::prelude::QuerierGetter; 6 | use cw_orch_daemon::queriers::Ibc; 7 | use cw_orch_daemon::queriers::{Bank, Staking}; 8 | pub const TEST_MNEMONIC: &str="scare silent genuine cheese monitor industry item cloth pet gather cruise long confirm van lunar tomato scrub silk guide eight truly rural remember swim"; 9 | 10 | pub fn main() -> AnyResult<()> { 11 | // We start by creating a daemon. This daemon will be used to interact with the chain. 12 | let daemon = Daemon::builder(cw_orch::daemon::networks::JUNO_1) // chain parameter 13 | .mnemonic(TEST_MNEMONIC) 14 | .build()?; 15 | 16 | // We do an actual bank query on MAINNET 17 | let bank_query_client: Bank = daemon.querier(); 18 | let sender = Addr::unchecked("juno185hgkqs8q8ysnc8cvkgd8j2knnq2m0ah6ae73gntv9ampgwpmrxqc5vwdr"); 19 | let balance_result = bank_query_client.balance(&sender, None)?; 20 | println!("Balance of {} : {:?}", sender, balance_result); 21 | 22 | // We do an actual Staking query on MAINNET 23 | let staking_query_client: Staking = daemon.querier(); 24 | let validator = 25 | Addr::unchecked("junovaloper185hgkqs8q8ysnc8cvkgd8j2knnq2m0ah6ae73gntv9ampgwpmrxqlfzywn"); 26 | let validator_result = daemon 27 | .rt_handle 28 | .block_on(staking_query_client._validator(&validator))?; 29 | println!("Validator info of {} : {:?}", sender, validator_result); 30 | 31 | // We do an actual IBC query on MAINNET 32 | let ibc_query_client: Ibc = daemon.querier(); 33 | let port_id = "transfer"; 34 | let channel_id = "channel-0"; 35 | let channel_result = daemon 36 | .rt_handle 37 | .block_on(ibc_query_client._channel(port_id, channel_id))?; 38 | println!( 39 | "Channel info of {port_id}:{channel_id} : {:?}", 40 | channel_result 41 | ); 42 | 43 | Ok(()) 44 | } 45 | -------------------------------------------------------------------------------- /cw-orch/src/daemon.rs: -------------------------------------------------------------------------------- 1 | //! `Daemon` and `DaemonAsync` execution environments. 2 | //! 3 | //! The `Daemon` type is a synchronous wrapper around the `DaemonAsync` type and can be used as a contract execution environment. 4 | pub use cw_orch_daemon::*; 5 | -------------------------------------------------------------------------------- /cw-orch/src/error.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | pub use cw_orch_core::CwEnvError as CwOrchError; 4 | -------------------------------------------------------------------------------- /cw-orch/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc(html_logo_url = "https://raw.githubusercontent.com/AbstractSDK/assets/mainline/logo.svg")] 2 | #![doc = include_str ! (concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] 3 | #![deny(missing_docs)] 4 | 5 | // macros 6 | pub use cw_orch_contract_derive::interface; 7 | pub use cw_orch_fns_derive::{ExecuteFns, QueryFns}; 8 | 9 | // prelude 10 | #[cfg(not(target_arch = "wasm32"))] 11 | pub mod prelude; 12 | 13 | #[cfg(not(target_arch = "wasm32"))] 14 | mod error; 15 | 16 | #[cfg(not(target_arch = "wasm32"))] 17 | #[cfg(feature = "daemon")] 18 | pub mod daemon; 19 | 20 | #[cfg(not(target_arch = "wasm32"))] 21 | #[cfg(feature = "snapshot-testing")] 22 | pub mod snapshots; 23 | 24 | #[cfg(not(target_arch = "wasm32"))] 25 | /// used to avoid repeating the #[cfg(not(target_arch = "wasm32"))] macro for each export 26 | pub mod wasm_protected { 27 | 28 | /// Re-export anyhow for use in the macros 29 | pub extern crate anyhow; 30 | 31 | // This re-export should not be touched or the derive macros WILL break 32 | pub use cw_orch_core as core; 33 | pub use cw_orch_core::{build, contract}; 34 | 35 | /// Related to execution environments 36 | pub mod environment { 37 | pub use cw_orch_core::environment::*; 38 | } 39 | /// Related environment variables definition 40 | pub mod env_vars { 41 | pub use cw_orch_core::CoreEnvVars; 42 | #[cfg(feature = "daemon")] 43 | pub use cw_orch_daemon::{env::default_state_folder, env::DaemonEnvVars}; 44 | } 45 | pub use cw_orch_mock as mock; 46 | 47 | /// Re-export tokio, the async runtime when using daemons. 48 | #[cfg(feature = "daemon")] 49 | pub extern crate tokio; 50 | 51 | // Rexporting for the macro to work properly 52 | #[cfg(feature = "snapshot-testing")] 53 | pub extern crate insta; 54 | #[cfg(feature = "snapshot-testing")] 55 | pub extern crate sanitize_filename; 56 | } 57 | 58 | #[cfg(not(target_arch = "wasm32"))] 59 | pub use wasm_protected::*; 60 | -------------------------------------------------------------------------------- /cw-orch/src/snapshots/cw_orch__snapshots__tests__multiple_contracts_snapshot_test.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: cw-orch/src/snapshots.rs 3 | expression: all_storage 4 | snapshot_kind: text 5 | --- 6 | counter_contract: 7 | - - contract_info 8 | - "{\"contract\":\"crates.io:counter\",\"version\":\"0.27.1\"}" 9 | - - state 10 | - "{\"count\":1,\"owner\":\"cosmwasm1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qlm3aqg\"}" 11 | second-counter-contract: 12 | - - contract_info 13 | - "{\"contract\":\"crates.io:counter\",\"version\":\"0.27.1\"}" 14 | - - state 15 | - "{\"count\":4,\"owner\":\"cosmwasm1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qlm3aqg\"}" 16 | third-counter-contract: 17 | - - contract_info 18 | - "{\"contract\":\"crates.io:counter\",\"version\":\"0.27.1\"}" 19 | - - state 20 | - "{\"count\":3,\"owner\":\"cosmwasm1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qlm3aqg\"}" 21 | -------------------------------------------------------------------------------- /cw-orch/src/snapshots/cw_orch__snapshots__tests__snapshot_test.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: cw-orch/src/snapshots.rs 3 | expression: all_storage 4 | snapshot_kind: text 5 | --- 6 | counter_contract: 7 | - - contract_info 8 | - "{\"contract\":\"crates.io:counter\",\"version\":\"0.27.1\"}" 9 | - - state 10 | - "{\"count\":1,\"owner\":\"cosmwasm1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qlm3aqg\"}" 11 | -------------------------------------------------------------------------------- /cw-orch/tests/fns_macro.rs: -------------------------------------------------------------------------------- 1 | use mock_contract::{ExecuteMsgFns, InstantiateMsg, MockContract, QueryMsgFns}; 2 | 3 | use cosmwasm_std::Event; 4 | 5 | use cw_orch::prelude::CwOrchUpload; 6 | use cw_orch::prelude::{CwOrchInstantiate, Mock}; 7 | 8 | #[test] 9 | fn test_execute() { 10 | let contract = MockContract::new("test:mock_contract", Mock::new("Ghazshag")); 11 | contract.upload().unwrap(); 12 | 13 | contract.instantiate(&InstantiateMsg {}, None, &[]).unwrap(); 14 | 15 | let response = contract.first_message().unwrap(); 16 | 17 | response.has_event( 18 | &Event::new("wasm") 19 | .add_attribute("_contract_addr", "contract0") 20 | .add_attribute("action", "first message passed"), 21 | ); 22 | 23 | contract.second_message("".to_string(), &[]).unwrap_err(); 24 | } 25 | 26 | #[test] 27 | fn test_query() { 28 | let contract = MockContract::new("test:mock_contract", Mock::new("Ghazshag")); 29 | contract.upload().unwrap(); 30 | 31 | contract.instantiate(&InstantiateMsg {}, None, &[]).unwrap(); 32 | 33 | let response = contract.first_query().unwrap(); 34 | assert_eq!(response, "first query passed"); 35 | 36 | contract.second_query("".to_string()).unwrap_err(); 37 | } 38 | -------------------------------------------------------------------------------- /cw-orch/tests/new_chain.rs: -------------------------------------------------------------------------------- 1 | // ANCHOR: NEW_NETWORK_INFO 2 | 3 | use cw_orch::environment::{ChainInfo, ChainKind, NetworkInfo}; 4 | 5 | pub const NEW_NETWORK_INFO: NetworkInfo = NetworkInfo { 6 | chain_name: "osmosis", 7 | pub_address_prefix: "osmo", 8 | coin_type: 118, 9 | }; 10 | 11 | pub const NEW_CHAIN_INFO: ChainInfo = ChainInfo { 12 | chain_id: "osmosis-4", 13 | gas_denom: "uosmo", 14 | gas_price: 7575.8, 15 | grpc_urls: &["Some GRPC URLS"], 16 | lcd_url: None, // Not necessary for cw-orch 17 | fcd_url: None, // Not necessary for cw-orch 18 | network_info: NEW_NETWORK_INFO, 19 | kind: ChainKind::Mainnet, 20 | }; 21 | // ANCHOR_END: NEW_NETWORK_INFO 22 | -------------------------------------------------------------------------------- /cw-orch/tests/underlying_into.rs: -------------------------------------------------------------------------------- 1 | // ANCHOR: underlying_into 2 | use cw_orch::interface; 3 | use cw_orch::prelude::*; 4 | 5 | // An execute message that is generic. 6 | #[cosmwasm_schema::cw_serde] 7 | pub enum GenericExecuteMsg { 8 | Generic(T), 9 | Nested(NestedMessageType), 10 | } 11 | 12 | // This is the message that will be used on our contract 13 | type ExecuteMsg = GenericExecuteMsg; 14 | #[cosmwasm_schema::cw_serde] 15 | #[derive(cw_orch::ExecuteFns)] 16 | pub enum Foo { 17 | Bar { a: String }, 18 | } 19 | 20 | impl From for ExecuteMsg { 21 | fn from(msg: Foo) -> Self { 22 | ExecuteMsg::Generic(msg) 23 | } 24 | } 25 | 26 | #[cosmwasm_schema::cw_serde] 27 | #[derive(cw_orch::ExecuteFns)] 28 | pub enum NestedMessageType { 29 | Test { b: u64 }, 30 | } 31 | 32 | impl From for ExecuteMsg { 33 | fn from(msg: NestedMessageType) -> Self { 34 | ExecuteMsg::Nested(msg) 35 | } 36 | } 37 | 38 | #[interface(Empty, ExecuteMsg, Empty, Empty)] 39 | struct Example; 40 | 41 | impl Example { 42 | pub fn test_macro(&self) { 43 | // function `bar` is available now! 44 | self.bar("hello".to_string()).unwrap(); 45 | 46 | // function `test` is available now! 47 | self.test(65u64).unwrap(); 48 | } 49 | } 50 | // ANCHOR_END: underlying_into 51 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | doctest_cache -------------------------------------------------------------------------------- /docs/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["CyberHoward", "Riada"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "cw-orchestrator documentation" 7 | 8 | [preprocessor.keeper] 9 | command = "mdbook-keeper" 10 | externs = ["cosmwasm_schema", "cosmwasm_std", "counter_contract", "cw_orch_interchain", "anyhow"] 11 | manifest_dir = "../" 12 | 13 | [output.html] 14 | curly-quotes = true 15 | default-theme = "light" 16 | edit-url-template = "https://github.com/AbstractSDK/cw-orchestrator/edit/main/docs/{path}" 17 | git-repository-icon = "fa-github" 18 | git-repository-url = "https://github.com/AbstractSDK/cw-orchestrator" 19 | preferred-dark-theme = "navy" 20 | 21 | [extern] 22 | # Define the external crate and its features 23 | cw-orch-interchain = { path = "../cw-orch-interchain", features = ["daemon"] } 24 | -------------------------------------------------------------------------------- /docs/src/chains/archway.md: -------------------------------------------------------------------------------- 1 | # Archway 2 | 3 | Archway is a smart contract platform that directly rewards developers for their contributions. With built-in incentives, Archway equips developers with tools to craft and deploy scalable cross-chain dApps. As these dApps enhance the network's value, developers enjoy further rewards. 4 | 5 | [Archway Website](https://archway.io/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/archway.rs:archway}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::ARCHWAY_1`. 14 | ## References 15 | 16 | - [Archway Documentation](https://docs.archway.io/) 17 | - [Archway Discord](https://discord.gg/archwayhq) 18 | -------------------------------------------------------------------------------- /docs/src/chains/bitsong.md: -------------------------------------------------------------------------------- 1 | # Bitsong 2 | 3 | BitSong is a multifunctional blockchain-based ecosystem built to empower the music industry. It unites artists, fans, distributors in an environment where music, merchandise, and fan loyalty are assets of value. BitSong’s decentralized ecosystem of services provides the global music community with a trustless marketplace for music streaming, Fan Tokens, and NFTs, powered by the BTSG token. 4 | 5 | [Bitsongs Website](https://bitsong.io/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/bitsong.rs:bitsong}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::BITSONG_1`. 14 | ## References 15 | 16 | - [Bitsong Documentation](https://docs.bitsong.io/) 17 | - [Bitsong Discord](https://discord.gg/M2fJKfMHAw) 18 | -------------------------------------------------------------------------------- /docs/src/chains/cosmos.md: -------------------------------------------------------------------------------- 1 | # Cosmos Hub 2 | 3 | The Cosmos Hub is the first of thousands of interconnected blockchains that will eventually comprise the Cosmos Network. The primary token of the Cosmos Hub is the ATOM, but the Hub will support many tokens in the future. 4 | 5 | [Cosmos Hub Website](https://cosmos.network/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/cosmos.rs:cosmos}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::COSMOS_HUB_TESTNET`. 14 | ## References 15 | 16 | - [Cosmos Hub Documentation](https://hub.cosmos.network/main) 17 | - [Cosmos Hub Discord](https://discord.gg/interchain) 18 | -------------------------------------------------------------------------------- /docs/src/chains/injective.md: -------------------------------------------------------------------------------- 1 | # Injective 2 | 3 | Injective is a unique blockchain tailored for finance, offering out-of-the-box modules like a fully decentralized orderbook. As an open smart contracts platform, it hosts a suite of decentralized apps designed for optimal user experience. Dive into Injective and unlock efficient capital allocation in decentralized financial markets. 4 | 5 | [Visit Injective's Website](https://injective.com/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/injective.rs:injective}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | To interact with contracts on Injective, first enable the `eth` feature for cw-orchestrator. Injective supports EVM-based addresses, and this will enable their use within cw-orchestrator. 14 | 15 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::INJECTIVE_1`. 16 | 17 | ## References 18 | 19 | - [Injective Documentation](https://docs.injective.network/) 20 | - [Injective Discord](https://discord.gg/injective) 21 | -------------------------------------------------------------------------------- /docs/src/chains/juno.md: -------------------------------------------------------------------------------- 1 | # Juno 2 | 3 | Juno stands as the central hub for CosmWasm smart contracts, underpinned by the InterWasm DAO. As a global, open-source, and permission-less platform, Juno champions the forefront of CosmWasm development, enabling developers to seamlessly deploy inter-chain smart contracts crafted in Rust. The network's inclusive design ensures that anyone can innovate and engage with inter-chain applications. 4 | 5 | [Visit Juno's Website](https://junonetwork.io/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/juno.rs:juno}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::JUNO_1`. 14 | 15 | ## References 16 | 17 | - [Juno Documentation](https://docs.junonetwork.io/juno/readme) 18 | - [Juno Discord](https://discord.junonetwork.io/) 19 | -------------------------------------------------------------------------------- /docs/src/chains/kujira.md: -------------------------------------------------------------------------------- 1 | # Kujira 2 | 3 | A decentralized ecosystem for protocols, builders and web3 users seeking sustainable FinTech. 4 | 5 | [Visit Kujira's Website](https://kujira.network/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/kujira.rs:kujira}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::KAIYO_1`. 14 | 15 | ## References 16 | 17 | - [Kujira Documentation](https://docs.kujira.app/introduction/readme) 18 | - [Kujira Discord](https://discord.gg/teamkujira) 19 | -------------------------------------------------------------------------------- /docs/src/chains/landslide.md: -------------------------------------------------------------------------------- 1 | # Landslide 2 | 3 | Landslide is the Avalanche-powered Interchain Hub connecting all blockchains to IBC, Web3's most secure interoperability solution. Expanding user bases and unlocking cross-chain potential. 4 | 5 | [Visit Landslide's Website](https://www.landslide.network/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/landslide.rs:landslide}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::LOCAL_LANDSLIDE`. 14 | 15 | ## References 16 | 17 | - [Landslide Documentation](https://docs.landslide.network/) 18 | - [Landslide Discord](https://discord.com/invite/AQHkYmu46X) 19 | -------------------------------------------------------------------------------- /docs/src/chains/migaloo.md: -------------------------------------------------------------------------------- 1 | # Migaloo 2 | 3 | Migaloo is a permission-less, open source network for decentralized interoperable applications running the latest tech. 4 | 5 | [Visit Migaloo's Docs](https://docs.migaloo.zone/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/migaloo.rs:migaloo}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::MIGALOO_1`. 14 | 15 | ## References 16 | 17 | - [Migaloo Documentation](https://docs.migaloo.zone/intro) 18 | - [White Whale Discord](https://discord.gg/pc5EXCBfEwa) 19 | -------------------------------------------------------------------------------- /docs/src/chains/neutron.md: -------------------------------------------------------------------------------- 1 | # Neutron 2 | 3 | The most secure CosmWasm platform in Cosmos, Neutron lets smart-contracts leverage bleeding-edge Interchain technology with minimal overhead. 4 | 5 | [Visit Neutron's Website](https://neutron.org/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/neutron.rs:neutron}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::NEUTRON_1`. 14 | 15 | ## References 16 | 17 | - [Neutron Documentation](https://docs.neutron.org/) 18 | - [Neutron Discord](https://discord.com/invite/zRT2ZkQsxA) 19 | -------------------------------------------------------------------------------- /docs/src/chains/nibiru.md: -------------------------------------------------------------------------------- 1 | # Nibiru 2 | 3 | Nibiru is a breakthrough smart contract platform providing superior throughput, reduced latency, and improved security, all driven by Web Assembly (Wasm) smart contracts. Nibiru simplifies the existing DeFi trading solutions through vertical integration. 4 | 5 | [Nibiru Website](https://nibiru.fi/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/nibiru.rs:nibiru}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::NIBIRU_ITN_2`. 14 | 15 | ## References 16 | 17 | - [Nibiru Documentation](https://nibiru.fi/docs/) 18 | - [Nibiru Discord](https://discord.gg/HFvbn7Wtud) 19 | -------------------------------------------------------------------------------- /docs/src/chains/osmosis.md: -------------------------------------------------------------------------------- 1 | # Osmosis 2 | 3 | Osmosis is a cutting-edge decentralized exchange built on the Cosmos network, designed for seamless asset swaps across various interconnected blockchains. As a trailblazer in AMM protocols, Osmosis empowers users with fast, secure, and efficient cross-chain liquidity solutions. The platform's innovative approach to DeFi positions it as a cornerstone in the Cosmos ecosystem, enabling anyone to effortlessly tap into the vast potential of inter-chain finance. 4 | 5 | [Visit Osmosis's Website](https://osmosis.zone/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/osmosis.rs:osmosis}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::OSMO_5`. 14 | 15 | ## References 16 | 17 | - [Osmosis Documentation](https://docs.osmosis.zone/) 18 | - [Osmosis Discord](https://discord.com/invite/osmosis) 19 | -------------------------------------------------------------------------------- /docs/src/chains/rollkit.md: -------------------------------------------------------------------------------- 1 | # Rollkit 2 | 3 | Rollkit is the open modular framework for sovereign rollups. Their mission is to empower developers to quickly innovate and create entire new classes of rollups with minimal tradeoffs. 4 | 5 | [Visit Rollkit's Website](https://rollkit.dev/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/rollkit.rs:rollkit}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::LOCAL_ROLLKIT`. 14 | 15 | ## Compatibility 16 | 17 | This integration has been tested using the [Rollkit Setup with CosmWasm](https://rollkit.dev/tutorials/cosmwasm). The following versions were used: 18 | 19 | - Mocha testnet node: `celestia/v0.15.0.beta.1` 20 | - Rollup node: `wasmd/v0.50.0` (which opens up port 9290 locally) 21 | - In order to use `cw-orchestrator` with this setup, the `LOCAL_MNEMONIC` [environment variable](../contracts/env-variable.md) needs to be assigned. You can find the right value for this mnemonic in the beginning of the console logs generated by the `bash init.sh` command in [the official RollKit docs](https://rollkit.dev/tutorials/cosmwasm#initialize-rollup). 22 | 23 | Please contact us on [Discord](http://discord.gg/uch3Tq3aym) if you have any issues. 24 | 25 | ## References 26 | 27 | - [Rollkit Documentation](https://rollkit.dev/learn/intro) 28 | - [Rollkit Setup with CosmWasm](https://rollkit.dev/tutorials/cosmwasm) 29 | -------------------------------------------------------------------------------- /docs/src/chains/sei.md: -------------------------------------------------------------------------------- 1 | # Sei 2 | 3 | Sei is the fastest Layer 1 blockchain, designed to scale with the industry. 4 | 5 | [Visit Sei's Website](https://www.sei.io/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/sei.rs:sei}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::SEI_DEVNET_3`. 14 | 15 | ## References 16 | 17 | - [Sei Documentation](https://docs.sei.io/) 18 | - [Sei Discord](https://discord.gg/sei) 19 | -------------------------------------------------------------------------------- /docs/src/chains/terra.md: -------------------------------------------------------------------------------- 1 | # Terra 2 | 3 | Fueled by a passionate community and deep developer talent pool, the Terra blockchain is built to enable the next generation of Web3 products and services. 4 | 5 | [Visit Terra's Website](https://www.terra.money/) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/terra.rs:terra}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::PHOENIX_1`. 14 | 15 | ## References 16 | 17 | - [Terra Documentation](https://docs.terra.money/) 18 | - [Terra Discord](https://terra.sc/discord) 19 | -------------------------------------------------------------------------------- /docs/src/chains/union.md: -------------------------------------------------------------------------------- 1 | # Union 2 | 3 | Union is the first infrastructure layer that unifies thousands of networks, unlocking horizontal scalability for any protocol. 4 | 5 | [Visit Union's Website](https://union.build) 6 | 7 | ```rust,ignore 8 | {{#include ../../../packages/cw-orch-networks/src/networks/union.rs:union}} 9 | ``` 10 | 11 | ## Usage 12 | 13 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::UNION_TESTNET`. 14 | 15 | ## References 16 | 17 | - [Union Documentation](https://union.build/docs/) 18 | - [Union Discord](https://discord.union.build) 19 | - [Union Testnet Faucet](https://app.union.build/faucet) 20 | -------------------------------------------------------------------------------- /docs/src/chains/xion.md: -------------------------------------------------------------------------------- 1 | # XION 2 | 3 | XION empowers developers and brands to create frictionless Web3 experiences, with a Generalized Abstraction layer that removes technical barriers for all users. 4 | 5 | 6 | 7 | [Visit XION's Website](https://xion.burnt.com/) 8 | 9 | ```rust,ignore 10 | {{#include ../../../packages/cw-orch-networks/src/networks/xion.rs:xion}} 11 | ``` 12 | 13 | ## Usage 14 | 15 | See how to setup your main function in the [main function](../contracts/scripting.md#main-function) section. Update the network passed into the `Daemon` builder to be `networks::XION_TESTNET_1`. 16 | 17 | ## References 18 | 19 | - [XION Documentation](https://docs.burnt.com/xion) 20 | - [XION Discord](https://discord.com/invite/burnt) 21 | -------------------------------------------------------------------------------- /docs/src/cli/index.md: -------------------------------------------------------------------------------- 1 | # Orchestrator Command Line Interface (CLI) 2 | 3 | Currently, each chain has its own CLI based on wasmd, which are incompatible with each other. With this in mind, we created cw-orch-cli. cw-orchestrator allows for easy chain switching, which is essential for cross-chain solutions. 4 | 5 | ## Prerequisites 6 | 7 | - Rust 8 | - OpenSSL 9 | 10 | ## Setup 11 | 12 | ```bash 13 | cargo install cw-orch-cli 14 | ``` 15 | 16 | ## Features 17 | 18 | Supported features of cw-orch-cli: 19 | 20 | - **[Keys management](./keys.md)**: Add, show or remove key for the CLI 21 | - **[Action](./cosmos_action.md)**: Perform cosmos action 22 | 23 | Feel free to request new features by [opening an issue](https://github.com/AbstractSDK/cw-orchestrator/issues/new)! 24 | -------------------------------------------------------------------------------- /docs/src/cli/keys.md: -------------------------------------------------------------------------------- 1 | # Key management 2 | 3 | To sign transactions, you need to have a stored key in the keyring. This is currently the only way to sign transactions, feel free to request other signing methods. 4 | 5 | ## Safety 6 | 7 | The keys are kept in an underlying platform-specific secure store(keyring) as seeds. To support different derivation paths we can't save it as key pair 8 | 9 | ## Features 10 | 11 | ### Add key 12 | 13 | Add key command saves provided or generated seed to the keyring: 14 | 15 | - Generate new random seed : `cw-orch-cli key add [NAME] new` 16 | - Recover from seed phrase: `cw-orch-cli key add [NAME] from-seed` 17 | - This command will give you prompt for your mnemonic 18 | 19 | ### Show seed of saved key 20 | 21 | Show seed command loads saved seed phrase from the keyring and outputs it: 22 | 23 | - Shows seed phrase of the key: `cw-orch-cli key show [NAME]` 24 | 25 | ### Show address 26 | 27 | Show address command generates public address for this key on chosen network: 28 | 29 | - Show address: `cw-orch-cli key show-address [NAME] [CHAIN_ID]` 30 | 31 | ### Remove key 32 | 33 | Remove key command deletes entry of provided key-id from the keyring: 34 | 35 | - Remove saved key: `cw-orch-cli key remove [NAME]` 36 | -------------------------------------------------------------------------------- /docs/src/contracts/integration-tests.md: -------------------------------------------------------------------------------- 1 | # Integration Tests 2 | 3 | Integration tests are very easy to write with cw-orch and are 100% compatible with actual on-chain deployment and scripting. We provide an overview of how they can be executed here. Find out more about how to setup your integration tests on the [Cw Multi Test page](../integrations/cw-multi-test.md) 4 | 5 | Start by creating a `tests` folder in your contract's dir. 6 | 7 | ```bash 8 | mkdir counter/tests 9 | ``` 10 | 11 | Then create a file called `integration_tests.rs` in the `tests` folder. 12 | 13 | ```bash 14 | touch counter/tests/integration_tests.rs 15 | ``` 16 | 17 | Now we can write our tests. Here's an example of a test that deploys the contract, increments the counter and then resets it. 18 | 19 | ```rust,ignore 20 | {{#include ../../../contracts-ws/contracts/counter/tests/integration_tests.rs:all}} 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/src/integrations/index.md: -------------------------------------------------------------------------------- 1 | # Integrations 2 | 3 | cw-orchestrator aims at allowing developers to interact with different execution environments with the exact same code base and syntax. 4 | 5 | In order to do so, it provides a set of traits and interfaces, e.g. for [contracts](../contracts/index.md) that can be implemented on execution structures. As of writing this documentation, the following execution environments are supported: 6 | 7 | - [Node interaction (grpc)](./daemon.md) 8 | - [Osmosis Test Tube](./osmosis-test-tube.md) 9 | - [Cw-Multi-test](./cw-multi-test.md) 10 | - [Clone Testing](./clone-testing.md) 11 | 12 | Those environments allow developers to test, deploy, manage, migrate, maintain, without having to switch programming languages, care for types and version compatibilities as they are enforced by the compiler and even change the syntax of the code used. 13 | 14 | The [Unit Tests](./unit-tests.md) page shows you how you can unit-test your contracts against actual on-chain data! 15 | -------------------------------------------------------------------------------- /docs/src/interchain/integrations/index.md: -------------------------------------------------------------------------------- 1 | # Interchain Execution Environment Integration 2 | 3 | When working with interchain applications, you will run into issues testing your application or even executing your application on real chains. The issues might me the following: 4 | 5 | ## Packet relaying 6 | 7 | When interacting with actual chains, you might not be able to make sure that packets have been relayed correctly and often times, developers rely on `sleep`, timeout, application specific events or data availability to follow their interchain executions. And this is a mess because this might not be reliable, or un-reusable and application specific code. With `cw-orch-interchain` we provide tooling to follow and assert your packet execution. This allows developers to create robust deployment, testing and maintenance code. [Try it out today](./daemon.md). 8 | 9 | ## Testing 10 | 11 | When testing interchain applications, you run into the following issues: 12 | 13 | ### No IBC testing framework available 14 | 15 | The most used library for cosmwasm testing is Cw-Multi-Test. However, this library doesn't support IBC. `cw-orch` provides interchain capabilities by default. [Try it out today](./mock.md). 16 | 17 | ### IBC testing with Custom Modules 18 | 19 | Some Chains have very interesting Custom Modules that work with IBC (IBC Queries on Neutron for instance). However, it's not possible to test those custom modules with local in-code testing frameworks[^1]. `cw-orchestrator` allows using `Starship`, a local testing framework that spins-up a mini cosmos ecosystem of chains and relayers locally. The used chains are clones of actual chain binaries So for instance, starship can spin up a neutron chain locally and test the logic directly against actual on-chain go binaries. [Try it out today](./starship.md). 20 | 21 | 22 | [^1]: Because that would require duplicating the go logic inside Rust code which is very time-consuming to do and maintain. -------------------------------------------------------------------------------- /docs/src/references.md: -------------------------------------------------------------------------------- 1 | # References 2 | 3 | Easy, right? Try building your contracts with Abstract for the same experience with smart contracts. 4 | Get started here. 5 | 6 | -------------------------------------------------------------------------------- /docs/src/setup/index.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | In this tutorial, you will find information on how to setup your working directory for cw-orchestrator integration. Because of the nature of smart contracts working directories, we have 2 separate tutorials depending on your setup: 4 | 5 | - [Single Contract setup tutorial](../setup/single-contract.md), if you're working with **a single contract**. 6 | - [Workspace setup tutorial](../setup/workspace/index.md), if you're working with **multiple contracts** within a cargo workspace environment. -------------------------------------------------------------------------------- /docs/src/setup/workspace/index.md: -------------------------------------------------------------------------------- 1 | # Workspace Tutorial 2 | 3 | In this tutorial, you will learn how to setup cw-orchestrator inside a workspace project. We present here the best practices for setting up an application composed of multiple contracts with the `cw-orch` crate. If you want a short version on how to integrate your contracts, we advise running to our [Quick Start guide](../../quick_start.md). 4 | 5 | > **NOTE**: A rust workspace is a simple way to have multiple contracts inside the same repository and are especially suited for applications in which multiple contracts communicate with each other. 6 | 7 | This tutorial has multiple components: 8 | 9 | - [Project Setup](./setup.md) 10 | - This tutorial helps you setup your project to have a rational workspace structure and all the dependencies needed for interacting with your contracts. 11 | - [Project Wrapper](./deploy.md) 12 | - This tutorial allows you to go further and simplify the way you interact with all the [interfaces you created](../../contracts/interfaces.md) included in your project. It presents best practices and usual project structure to keep your project organized. 13 | - [Collaborating](./collaboration.md) 14 | - This tutorial shows you how you can distribute your contract code, you deployment variables (code_ids, addresses...) for other projects to integrate with. This is the ultimate way to collaborate with other projects. 15 | -------------------------------------------------------------------------------- /hooks/pre-push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export PATH=$PATH:/usr/local/bin 3 | 4 | # Requirements: 5 | # 1. Have rust and cargo installed 6 | # 2. Have taplo installed (cargo install taplo-cli --locked) 7 | # 8 | # pre-push hook, used to perform static analysis checks on changed files. 9 | # 10 | # Install the hook with the --install option. 11 | 12 | project_toplevel=$(git rev-parse --show-toplevel) 13 | git_directory=$(git rev-parse --git-dir) 14 | 15 | install_hook() { 16 | mkdir -p "$git_directory/hooks" 17 | ln -sfv "$project_toplevel/hooks/pre-push.sh" "$git_directory/hooks/pre-push" 18 | } 19 | 20 | if [ "$1" = "--install" ]; then 21 | if [ -f "$git_directory/hooks/pre-push" ]; then 22 | read -r -p "There's an existing pre-push hook. Do you want to overwrite it? [y/N] " response 23 | case "$response" in 24 | [yY][eE][sS] | [yY]) 25 | install_hook 26 | ;; 27 | *) 28 | printf "Skipping hook installation :(" 29 | exit $? 30 | ;; 31 | esac 32 | else 33 | install_hook 34 | fi 35 | exit $? 36 | fi 37 | 38 | # cargo and toml fmt checks 39 | format_check() { 40 | printf "Starting file formatting check...\n" 41 | 42 | cd $project_toplevel || exit; 43 | # format rust code 44 | cargo fmt; 45 | # format toml files 46 | find . -type f -iname "*.toml" -print0 | xargs -0 taplo format 47 | 48 | sleep 1; # Give git time to find changed files. 49 | not_staged_file=$(git diff --name-only) 50 | if [ "$not_staged_file" != "" ]; then # it means the file changed and it's not staged, i.e. rustfmt did the job. 51 | git add . 52 | git commit -m "formatting" 53 | fi 54 | } 55 | 56 | # clippy checks 57 | lint_check() { 58 | printf "Starting clippy check...\n" 59 | cargo clippy --quiet -- -D warnings 60 | clippy_exit_code=$? 61 | if [ $clippy_exit_code -ne 0 ]; then 62 | printf "\nclippy found some issues. Fix them manually or run cargo clippy --fix." 63 | exit 1 64 | fi 65 | } 66 | 67 | lint_check 68 | format_check 69 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | test: 2 | cargo test 3 | 4 | install-docs: 5 | cargo install mdbook 6 | cargo install mdbook-keeper@0.3.0 7 | 8 | install-docs-fast: 9 | mkdir bin 10 | curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.35/mdbook-v0.4.35-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin 11 | 12 | setup-docs: 13 | cargo install mdbook-keeper@0.3.0 14 | 15 | serve-docs: 16 | (cd docs && mdbook serve --open) 17 | 18 | build-docs: 19 | (cd docs && mdbook build) 20 | 21 | doc-test: 22 | cargo test --doc 23 | mdbook build docs 24 | 25 | format: 26 | cargo fmt --all 27 | find . -type f -iname "*.toml" -print0 | xargs -0 taplo format 28 | 29 | 30 | -------------------------------------------------------------------------------- /networks.toml.example: -------------------------------------------------------------------------------- 1 | [juno-1] 2 | kind = "mainnet" 3 | chain_id = "juno-1" 4 | gas_denom = "ujuno" 5 | gas_price = 0.075 6 | grpc_urls = ["http://juno-grpc.polkachu.com:12690"] 7 | 8 | [juno-1.network_info] 9 | chain_name = "juno" 10 | pub_address_prefix = "juno" 11 | coin_type = 118 12 | -------------------------------------------------------------------------------- /packages/clone-testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Adapter for interacting with cw-multi-test via the cw-orchestrator tool" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-clone-testing" 7 | repository.workspace = true 8 | version = "0.9.2" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | cosmwasm-std = { workspace = true } 14 | 15 | cw-orch-core = { workspace = true } 16 | cw-orch-daemon = { workspace = true } 17 | cw-orch-mock = { workspace = true } 18 | 19 | clone-cw-multi-test = { version = "0.6.1" } 20 | 21 | anyhow = { workspace = true } 22 | cw-utils = { workspace = true } 23 | itertools = "0.12.0" 24 | log = { workspace = true } 25 | serde = { workspace = true } 26 | sha2 = "0.10.8" 27 | tokio = { workspace = true } 28 | tonic = { workspace = true } 29 | 30 | [dev-dependencies] 31 | cosmwasm-schema = "2.0.0" 32 | speculoos = { workspace = true } 33 | 34 | cw20 = { version = "2.0.0" } 35 | cw20-base = { version = "2.0.0" } 36 | 37 | counter-contract = { path = "../../contracts-ws/contracts/counter" } 38 | cw-orch = { path = "../../cw-orch", features = ["daemon"] } 39 | env_logger = "0.10.0" 40 | pretty_env_logger = "0.5.0" 41 | -------------------------------------------------------------------------------- /packages/clone-testing/README.md: -------------------------------------------------------------------------------- 1 | # Cosmwasm Orchestrator Mock 2 | 3 | A Mock-chain implementation of [cw-orch-core](../cw-orch-core/README.md) used by integration tests of contracts and testing against actual on-chain state. 4 | 5 | See [top-level README](../../README.md) 6 | -------------------------------------------------------------------------------- /packages/clone-testing/src/contract_instance.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::{ 2 | contract::interface_traits::{ContractInstance, Uploadable}, 3 | environment::{Environment, TxHandler}, 4 | CwEnvError, 5 | }; 6 | 7 | use crate::CloneTesting; 8 | 9 | pub trait WasmUpload: Uploadable + ContractInstance { 10 | fn upload_wasm(&self) -> Result<::Response, CwEnvError>; 11 | } 12 | 13 | impl WasmUpload for T 14 | where 15 | T: Uploadable + ContractInstance, 16 | { 17 | fn upload_wasm(&self) -> Result<::Response, CwEnvError> { 18 | self.environment().upload_wasm(self) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/clone-testing/src/queriers/bank.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use cosmwasm_std::{Addr, Coin}; 4 | use cw_orch_core::{ 5 | environment::{BankQuerier, Querier, QuerierGetter, StateInterface}, 6 | CwEnvError, 7 | }; 8 | 9 | use crate::{core::CloneTestingApp, CloneTesting}; 10 | 11 | pub struct CloneBankQuerier { 12 | app: Rc>, 13 | } 14 | 15 | impl CloneBankQuerier { 16 | fn new(mock: &CloneTesting) -> Self { 17 | Self { 18 | app: mock.app.clone(), 19 | } 20 | } 21 | } 22 | 23 | impl QuerierGetter for CloneTesting { 24 | fn querier(&self) -> CloneBankQuerier { 25 | CloneBankQuerier::new(self) 26 | } 27 | } 28 | 29 | impl Querier for CloneBankQuerier { 30 | type Error = CwEnvError; 31 | } 32 | 33 | impl BankQuerier for CloneBankQuerier { 34 | fn balance( 35 | &self, 36 | address: &Addr, 37 | denom: Option, 38 | ) -> Result, Self::Error> { 39 | if let Some(denom) = denom { 40 | let amount = self 41 | .app 42 | .borrow() 43 | .wrap() 44 | .query_balance(address, denom.clone())? 45 | .amount; 46 | Ok(vec![Coin { amount, denom }]) 47 | } else { 48 | let amount = self.app.borrow().wrap().query_all_balances(address)?; 49 | Ok(amount) 50 | } 51 | } 52 | 53 | fn supply_of(&self, denom: impl Into) -> Result { 54 | Ok(self.app.borrow().wrap().query_supply(denom)?) 55 | } 56 | 57 | fn total_supply(&self) -> Result, Self::Error> { 58 | unimplemented!() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/clone-testing/src/queriers/env.rs: -------------------------------------------------------------------------------- 1 | use crate::CloneTesting; 2 | 3 | use cw_orch_core::environment::{EnvironmentInfo, EnvironmentQuerier}; 4 | 5 | impl EnvironmentQuerier for CloneTesting { 6 | fn env_info(&self) -> EnvironmentInfo { 7 | let state = &self.state.borrow().daemon_state; 8 | EnvironmentInfo { 9 | chain_id: state.chain_data.chain_id.to_string(), 10 | chain_name: state.chain_data.network_info.chain_name.clone(), 11 | deployment_id: state.deployment_id.clone(), 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/clone-testing/src/queriers/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::{CloneTesting, MockState}; 2 | 3 | use clone_cw_multi_test::next_block; 4 | 5 | use cw_orch_core::{ 6 | environment::{DefaultQueriers, QueryHandler}, 7 | CwEnvError, 8 | }; 9 | pub mod bank; 10 | mod env; 11 | pub mod node; 12 | pub mod wasm; 13 | 14 | impl QueryHandler for CloneTesting { 15 | type Error = CwEnvError; 16 | 17 | fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { 18 | self.app.borrow_mut().update_block(|b| { 19 | b.height += amount; 20 | b.time = b.time.plus_seconds(5 * amount); 21 | }); 22 | Ok(()) 23 | } 24 | 25 | fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { 26 | self.app.borrow_mut().update_block(|b| { 27 | b.time = b.time.plus_seconds(secs); 28 | b.height += secs / 5; 29 | }); 30 | Ok(()) 31 | } 32 | 33 | fn next_block(&self) -> Result<(), CwEnvError> { 34 | self.app.borrow_mut().update_block(next_block); 35 | Ok(()) 36 | } 37 | } 38 | 39 | impl DefaultQueriers for CloneTesting { 40 | type Bank = bank::CloneBankQuerier; 41 | type Wasm = wasm::CloneWasmQuerier; 42 | type Node = node::CloneNodeQuerier; 43 | } 44 | -------------------------------------------------------------------------------- /packages/clone-testing/src/queriers/node.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use crate::{ 4 | core::{AppResponse, CloneTestingApp}, 5 | CloneTesting, 6 | }; 7 | use cw_orch_core::{ 8 | environment::{NodeQuerier, Querier, QuerierGetter, StateInterface}, 9 | CwEnvError, 10 | }; 11 | 12 | pub struct CloneNodeQuerier { 13 | app: Rc>, 14 | } 15 | 16 | impl CloneNodeQuerier { 17 | fn new(mock: &CloneTesting) -> Self { 18 | Self { 19 | app: mock.app.clone(), 20 | } 21 | } 22 | } 23 | 24 | impl Querier for CloneNodeQuerier { 25 | type Error = CwEnvError; 26 | } 27 | 28 | impl QuerierGetter for CloneTesting { 29 | fn querier(&self) -> CloneNodeQuerier { 30 | CloneNodeQuerier::new(self) 31 | } 32 | } 33 | 34 | impl NodeQuerier for CloneNodeQuerier { 35 | type Response = AppResponse; 36 | 37 | fn latest_block(&self) -> Result { 38 | Ok(self.app.borrow().block_info()) 39 | } 40 | 41 | fn block_by_height(&self, _height: u64) -> Result { 42 | unimplemented!() 43 | } 44 | 45 | fn block_height(&self) -> Result { 46 | let block_info = self.latest_block()?; 47 | 48 | Ok(block_info.height) 49 | } 50 | 51 | fn block_time(&self) -> Result { 52 | let block_info = self.latest_block()?; 53 | 54 | Ok(block_info.time.nanos() as u128) 55 | } 56 | 57 | fn simulate_tx(&self, _tx_bytes: Vec) -> Result { 58 | unimplemented!() 59 | } 60 | 61 | fn find_tx(&self, _hash: String) -> Result { 62 | unimplemented!() 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/clone-testing/tests/wasm-upload.rs: -------------------------------------------------------------------------------- 1 | use counter_contract::CounterContract; 2 | use cw_orch::prelude::*; 3 | use cw_orch_clone_testing::CloneTesting; 4 | use cw_orch_daemon::networks::JUNO_1; 5 | 6 | #[test] 7 | fn multiple_upload() -> anyhow::Result<()> { 8 | // ANCHOR: clone_testing_setup 9 | let chain = CloneTesting::new(JUNO_1)?; 10 | // ANCHOR_END: clone_testing_setup 11 | // ANCHOR: counter_contract_setup 12 | let contract = CounterContract::new(chain.clone()); 13 | // ANCHOR_END: counter_contract_setup 14 | 15 | // Either upload using the RUST code (`wrapper`) 16 | // ANCHOR: upload 17 | contract.upload()?; 18 | // ANCHOR_END: upload 19 | let code_id = contract.code_id()?; 20 | 21 | // OR upload using the wasm binaries 22 | // ANCHOR: upload_wasm 23 | use cw_orch_clone_testing::WasmUpload; 24 | contract.upload_wasm()?; 25 | // ANCHOR_END: upload_wasm 26 | let new_code_id = contract.code_id()?; 27 | 28 | assert_ne!(new_code_id, code_id); 29 | 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /packages/cw-orch-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | categories = ["development-tools"] 4 | description = "Scripting library for deploying and interacting with CosmWasm smart-contracts" 5 | edition = { workspace = true } 6 | keywords = ["cosmwasm", "blockchain"] 7 | license = { workspace = true } 8 | name = "cw-orch-core" 9 | readme = "README.md" 10 | repository = { workspace = true } 11 | version = "2.1.4" 12 | 13 | exclude = [".env"] 14 | 15 | [package.metadata.docs.rs] 16 | # passes all-features to cargo when building the docs. 17 | all-features = true 18 | 19 | [features] 20 | default = [] 21 | eth = ["dep:snailquote"] 22 | 23 | [dependencies] 24 | cosmwasm-std = { workspace = true } 25 | cw-multi-test = { workspace = true } 26 | serde = { workspace = true } 27 | thiserror = { workspace = true } 28 | 29 | anyhow = { workspace = true } 30 | log = { workspace = true } 31 | serde_json = { workspace = true } 32 | sha2 = { workspace = true } 33 | 34 | 35 | # Ethereum deps 36 | cosmos-sdk-proto = { workspace = true, features = ["cosmwasm"] } 37 | cw-storage-plus = { workspace = true } 38 | cw-utils = { workspace = true } 39 | dirs = "5.0.1" 40 | snailquote = { version = "0.3.1", optional = true } 41 | 42 | [dev-dependencies] 43 | anyhow = { workspace = true } 44 | speculoos = { workspace = true } 45 | -------------------------------------------------------------------------------- /packages/cw-orch-core/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/cw-orch-core/src/build.rs: -------------------------------------------------------------------------------- 1 | //! # Build Postfix Format 2 | //! Used to specify the build-postfix for contracts in the `Uploadable` trait. 3 | 4 | use crate::environment::ChainInfoOwned; 5 | 6 | /// Build name used for building the contract. 7 | /// See the [Abstract Optimizer](https://github.com/AbstractSDK/rust-optimizer). 8 | pub enum BuildPostfix<'a> { 9 | /// Default, doesn't look for anything but the contract name. 10 | None, 11 | /// Uses the chain to figure out the chain name. I.e. "uni-6" = "juno-1" -> "juno" post-fix on build. 12 | ChainName(&'a ChainInfoOwned), 13 | /// Uses the chain name as the build-postfix. I.e. "uni-6", "juno-1", "osmosis-5", ect. 14 | ChainID(&'a ChainInfoOwned), 15 | /// Use a custom post-fix to specify the artifact. 16 | Custom(String), 17 | } 18 | 19 | impl From> for String { 20 | fn from(value: BuildPostfix) -> Self { 21 | match value { 22 | BuildPostfix::None => "".to_string(), 23 | BuildPostfix::ChainName(chain) => chain.network_info.chain_name.clone(), 24 | BuildPostfix::ChainID(chain) => chain.chain_id.clone(), 25 | BuildPostfix::Custom(postfix) => postfix, 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/contract/mod.rs: -------------------------------------------------------------------------------- 1 | mod contract_instance; 2 | mod deploy; 3 | pub mod interface_traits; 4 | mod paths; 5 | 6 | pub use contract_instance::Contract; 7 | pub use deploy::Deploy; 8 | 9 | pub use paths::from_workspace as artifacts_dir_from_workspace; 10 | pub use paths::{ArtifactsDir, WasmPath}; 11 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/environment/envs.rs: -------------------------------------------------------------------------------- 1 | //! This module creates a trait `MutCwEnv`, that allows to create tests that are generic on all testing environments. 2 | //! This allows to set balance and the block for instance 3 | 4 | use super::{ 5 | queriers::{bank::BankQuerier, QuerierGetter}, 6 | QueryHandler, TxHandler, 7 | }; 8 | use cosmwasm_std::{Addr, Coin}; 9 | use cw_utils::NativeBalance; 10 | 11 | /// Describes a structure that contains an underlying execution environment 12 | pub trait Environment { 13 | /// Returns the chain that this structure executes on 14 | fn environment(&self) -> &Chain; 15 | } 16 | 17 | /// Signals a supported execution environment for CosmWasm contracts 18 | pub trait CwEnv: TxHandler + QueryHandler + Clone {} 19 | impl CwEnv for T {} 20 | 21 | pub trait MutCwEnv: BankSetter + CwEnv {} 22 | impl MutCwEnv for T where T: BankSetter + CwEnv {} 23 | 24 | pub trait BankSetter: TxHandler + QuerierGetter { 25 | type T: BankQuerier; 26 | 27 | fn set_balance( 28 | &mut self, 29 | address: &Addr, 30 | amount: Vec, 31 | ) -> Result<(), ::Error>; 32 | 33 | fn add_balance( 34 | &mut self, 35 | address: &Addr, 36 | amount: Vec, 37 | ) -> Result<(), ::Error> { 38 | // Query the current balance of the account 39 | let current_balance = QuerierGetter::::querier(self).balance(address, None)?; 40 | let future_balance = NativeBalance(current_balance) + NativeBalance(amount); 41 | // Set the balance with more funds 42 | self.set_balance(address, future_balance.into_vec())?; 43 | Ok(()) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/environment/mod.rs: -------------------------------------------------------------------------------- 1 | mod chain_info; 2 | mod envs; 3 | mod index_response; 4 | mod queriers; 5 | mod state; 6 | mod tx_handler; 7 | 8 | pub use chain_info::{ChainInfo, ChainInfoOwned, ChainKind, NetworkInfo, NetworkInfoOwned}; 9 | pub use envs::{BankSetter, CwEnv, Environment, MutCwEnv}; 10 | pub use index_response::IndexResponse; 11 | pub use queriers::{ 12 | bank::BankQuerier, 13 | env::{EnvironmentInfo, EnvironmentQuerier}, 14 | node::NodeQuerier, 15 | wasm::{AsyncWasmQuerier, WasmQuerier}, 16 | DefaultQueriers, Querier, QuerierGetter, QueryHandler, 17 | }; 18 | pub use state::{ChainState, StateInterface}; 19 | pub use tx_handler::{AccessConfig, TxHandler, TxResponse}; 20 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/environment/queriers/bank.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::{Addr, Coin}; 2 | 3 | use super::Querier; 4 | 5 | pub trait BankQuerier: Querier { 6 | /// Query the bank balance of a given address 7 | /// If denom is None, returns all balances 8 | fn balance(&self, address: &Addr, denom: Option) -> Result, Self::Error>; 9 | 10 | /// Query total supply in the bank 11 | fn total_supply(&self) -> Result, Self::Error>; 12 | 13 | /// Query total supply in the bank for a denom 14 | fn supply_of(&self, denom: impl Into) -> Result; 15 | } 16 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/environment/queriers/env.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug)] 2 | pub struct EnvironmentInfo { 3 | pub chain_id: String, 4 | pub chain_name: String, 5 | pub deployment_id: String, 6 | } 7 | 8 | pub trait EnvironmentQuerier { 9 | /// Get some details about the environment. 10 | fn env_info(&self) -> EnvironmentInfo; 11 | } 12 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/environment/queriers/node.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::BlockInfo; 2 | 3 | use crate::environment::IndexResponse; 4 | use std::fmt::Debug; 5 | 6 | use super::Querier; 7 | 8 | pub trait NodeQuerier: Querier { 9 | type Response: IndexResponse + Debug + Send + Clone; 10 | 11 | /// Returns latests block information 12 | fn latest_block(&self) -> Result; 13 | 14 | /// Returns block information fetched by height 15 | fn block_by_height(&self, height: u64) -> Result; 16 | 17 | /// Returns current block height 18 | fn block_height(&self) -> Result; 19 | /// Returns the block timestamp (since unix epoch) in nanos 20 | fn block_time(&self) -> Result; 21 | 22 | /// Simulate TX 23 | fn simulate_tx(&self, tx_bytes: Vec) -> Result; 24 | 25 | /// Find TX by hash 26 | fn find_tx(&self, hash: String) -> Result; 27 | } 28 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/error.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | use std::{ 4 | env, 5 | num::{ParseFloatError, ParseIntError}, 6 | str::ParseBoolError, 7 | }; 8 | 9 | use cosmwasm_std::Instantiate2AddressError; 10 | use thiserror::Error; 11 | 12 | /// cw-orchestrator error wrapper using thiserror. 13 | #[derive(Error, Debug)] 14 | pub enum CwEnvError { 15 | #[error(transparent)] 16 | CosmWasmError(#[from] cosmwasm_std::StdError), 17 | #[error("Code id for {0} not found in store")] 18 | CodeIdNotInStore(String), 19 | #[error("Contract address for {0} not found in store")] 20 | AddrNotInStore(String), 21 | #[error(transparent)] 22 | IOErr(#[from] ::std::io::Error), 23 | #[error(transparent)] 24 | SerdeJson(#[from] ::serde_json::Error), 25 | #[error(transparent)] 26 | EnvvarError(#[from] env::VarError), 27 | #[error(transparent)] 28 | ParseFloatError(#[from] ParseFloatError), 29 | #[error(transparent)] 30 | ParseIntError(#[from] ParseIntError), 31 | #[error(transparent)] 32 | ParseBoolError(#[from] ParseBoolError), 33 | #[error(transparent)] 34 | Instantiate2AddressError(#[from] Instantiate2AddressError), 35 | #[error("File must be a wasm file")] 36 | NotWasm, 37 | #[error("Could not find wasm file with name {0} in artifacts:{1} dir")] 38 | WasmNotFound(String, String), 39 | #[error("calling contract with unimplemented action")] 40 | NotImplemented, 41 | #[error(transparent)] 42 | AnyError(#[from] ::anyhow::Error), 43 | #[error("Generic Error {0}")] 44 | StdErr(String), 45 | #[error("Environment variable not defined {0}")] 46 | EnvVarNotPresentNamed(String), 47 | } 48 | 49 | impl CwEnvError { 50 | pub fn root(&self) -> &dyn std::error::Error { 51 | match self { 52 | CwEnvError::AnyError(e) => e.root_cause(), 53 | _ => panic!("Unexpected error type"), 54 | } 55 | } 56 | 57 | pub fn downcast(self) -> anyhow::Result 58 | where 59 | E: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static, 60 | { 61 | match self { 62 | CwEnvError::AnyError(e) => e.downcast(), 63 | _ => panic!("Unexpected error type"), 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod contract; 2 | pub mod env; 3 | pub use env::CoreEnvVars; 4 | pub mod environment; 5 | 6 | pub mod build; 7 | mod error; 8 | pub mod log; 9 | pub use error::CwEnvError; 10 | 11 | pub use serde_json; 12 | -------------------------------------------------------------------------------- /packages/cw-orch-core/src/log.rs: -------------------------------------------------------------------------------- 1 | const CONNECTIVITY_LOGS: &str = "Connectivity"; 2 | const QUERY_LOGS: &str = "Query"; 3 | const CONTRACT_LOGS: &str = "Contract"; 4 | const TRANSACTION_LOGS: &str = "Transaction"; 5 | const LOCAL_LOGS: &str = "Local"; 6 | 7 | fn format_aligned(a: &str) -> String { 8 | format!("{:>12}", a) 9 | } 10 | 11 | pub fn connectivity_target() -> String { 12 | format_aligned(CONNECTIVITY_LOGS) 13 | } 14 | pub fn query_target() -> String { 15 | format_aligned(QUERY_LOGS) 16 | } 17 | pub fn contract_target() -> String { 18 | format_aligned(CONTRACT_LOGS) 19 | } 20 | pub fn transaction_target() -> String { 21 | format_aligned(TRANSACTION_LOGS) 22 | } 23 | pub fn local_target() -> String { 24 | format_aligned(LOCAL_LOGS) 25 | } 26 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Adapter for interacting with cw-multi-test via the cw-orchestrator tool" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-mock" 7 | repository.workspace = true 8 | version = "0.24.4" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | cosmwasm-std = { workspace = true, features = ["cosmwasm_1_2"] } 14 | cw-multi-test = { workspace = true } 15 | cw-orch-core = { workspace = true } 16 | cw-utils = { workspace = true } 17 | log = { workspace = true } 18 | serde = { workspace = true } 19 | sha2 = { workspace = true } 20 | 21 | [dev-dependencies] 22 | cw20 = { version = "2.0.0" } 23 | cw20-base = { version = "2.0.0" } 24 | speculoos = { workspace = true } 25 | 26 | anyhow = { workspace = true } 27 | mock-contract = { path = "../../contracts-ws/contracts/mock_contract" } 28 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/README.md: -------------------------------------------------------------------------------- 1 | # Cosmwasm Orchestrator Mock 2 | A Mock-chain implementation of [cw-orch-core](../cw-orch-core/README.md) used by integration tests of contracts 3 | 4 | See [top-level README](../../README.md) -------------------------------------------------------------------------------- /packages/cw-orch-mock/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Integration testing execution environment backed by a [cw-multi-test](cw_multi_test) App. 2 | //! It has an associated state that stores deployment information for easy retrieval and contract interactions. 3 | 4 | // Export our fork 5 | pub extern crate cw_multi_test; 6 | 7 | mod bech32; 8 | mod core; 9 | pub mod queriers; 10 | mod simple; 11 | mod state; 12 | 13 | pub use self::core::{Mock, MockBase, MockBech32}; 14 | 15 | pub type MockApp = self::core::MockApp; 16 | pub type MockAppBech32 = self::core::MockApp; 17 | 18 | use cosmwasm_std::testing::MockApi; 19 | use cw_multi_test::MockApiBech32; 20 | pub use state::MockState; 21 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/src/queriers/bank.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use cosmwasm_std::{Addr, Api, Coin}; 4 | use cw_orch_core::{ 5 | environment::{ 6 | QuerierGetter, StateInterface, {BankQuerier, Querier}, 7 | }, 8 | CwEnvError, 9 | }; 10 | 11 | use crate::{core::MockApp, MockBase}; 12 | 13 | pub struct MockBankQuerier { 14 | app: Rc>>, 15 | } 16 | 17 | impl MockBankQuerier { 18 | fn new(mock: &MockBase) -> Self { 19 | Self { 20 | app: mock.app.clone(), 21 | } 22 | } 23 | } 24 | 25 | impl QuerierGetter> for MockBase { 26 | fn querier(&self) -> MockBankQuerier { 27 | MockBankQuerier::new(self) 28 | } 29 | } 30 | 31 | impl Querier for MockBankQuerier { 32 | type Error = CwEnvError; 33 | } 34 | 35 | impl BankQuerier for MockBankQuerier { 36 | fn balance( 37 | &self, 38 | address: &Addr, 39 | denom: Option, 40 | ) -> Result, Self::Error> { 41 | if let Some(denom) = denom { 42 | let amount = self 43 | .app 44 | .borrow() 45 | .wrap() 46 | .query_balance(address, denom.clone())? 47 | .amount; 48 | Ok(vec![Coin { amount, denom }]) 49 | } else { 50 | let amount = self.app.borrow().wrap().query_all_balances(address)?; 51 | Ok(amount) 52 | } 53 | } 54 | 55 | fn supply_of(&self, denom: impl Into) -> Result { 56 | Ok(self.app.borrow().wrap().query_supply(denom)?) 57 | } 58 | 59 | fn total_supply(&self) -> Result, Self::Error> { 60 | unimplemented!() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/src/queriers/env.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::Api; 2 | use cw_orch_core::environment::{ 3 | EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, 4 | }; 5 | 6 | use crate::MockBase; 7 | 8 | impl EnvironmentQuerier for MockBase { 9 | fn env_info(&self) -> EnvironmentInfo { 10 | let block_info = self.block_info().unwrap(); 11 | let chain_id = block_info.chain_id.clone(); 12 | let chain_name = chain_id.rsplitn(2, '-').last().unwrap().to_string(); 13 | 14 | EnvironmentInfo { 15 | chain_id, 16 | chain_name, 17 | deployment_id: "default".to_string(), 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/src/queriers/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::MockBase; 2 | 3 | use cosmwasm_std::Api; 4 | use cw_multi_test::next_block; 5 | use cw_orch_core::{ 6 | environment::{DefaultQueriers, QueryHandler, StateInterface}, 7 | CwEnvError, 8 | }; 9 | 10 | pub mod bank; 11 | mod env; 12 | pub mod node; 13 | pub mod wasm; 14 | 15 | impl QueryHandler for MockBase { 16 | type Error = CwEnvError; 17 | 18 | fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { 19 | self.app.borrow_mut().update_block(|b| { 20 | b.height += amount; 21 | b.time = b.time.plus_seconds(5 * amount); 22 | }); 23 | Ok(()) 24 | } 25 | 26 | fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { 27 | self.app.borrow_mut().update_block(|b| { 28 | b.time = b.time.plus_seconds(secs); 29 | b.height += secs / 5; 30 | }); 31 | Ok(()) 32 | } 33 | 34 | fn next_block(&self) -> Result<(), CwEnvError> { 35 | self.app.borrow_mut().update_block(next_block); 36 | Ok(()) 37 | } 38 | } 39 | 40 | impl DefaultQueriers for MockBase { 41 | type Bank = bank::MockBankQuerier; 42 | type Wasm = wasm::MockWasmQuerier; 43 | type Node = node::MockNodeQuerier; 44 | } 45 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/src/queriers/node.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use cosmwasm_std::Api; 4 | use cw_multi_test::AppResponse; 5 | use cw_orch_core::{ 6 | environment::{NodeQuerier, Querier, QuerierGetter, StateInterface}, 7 | CwEnvError, 8 | }; 9 | 10 | use crate::{core::MockApp, MockBase}; 11 | 12 | pub struct MockNodeQuerier { 13 | app: Rc>>, 14 | } 15 | 16 | impl MockNodeQuerier { 17 | fn new(mock: &MockBase) -> Self { 18 | Self { 19 | app: mock.app.clone(), 20 | } 21 | } 22 | } 23 | 24 | impl Querier for MockNodeQuerier { 25 | type Error = CwEnvError; 26 | } 27 | 28 | impl QuerierGetter> for MockBase { 29 | fn querier(&self) -> MockNodeQuerier { 30 | MockNodeQuerier::new(self) 31 | } 32 | } 33 | 34 | impl NodeQuerier for MockNodeQuerier { 35 | type Response = AppResponse; 36 | 37 | fn latest_block(&self) -> Result { 38 | Ok(self.app.borrow().block_info()) 39 | } 40 | 41 | fn block_by_height(&self, _height: u64) -> Result { 42 | unimplemented!() 43 | } 44 | 45 | fn block_height(&self) -> Result { 46 | let block_info = self.latest_block()?; 47 | 48 | Ok(block_info.height) 49 | } 50 | 51 | fn block_time(&self) -> Result { 52 | let block_info = self.latest_block()?; 53 | 54 | Ok(block_info.time.nanos() as u128) 55 | } 56 | 57 | fn simulate_tx(&self, _tx_bytes: Vec) -> Result { 58 | unimplemented!() 59 | } 60 | 61 | fn find_tx(&self, _hash: String) -> Result { 62 | unimplemented!() 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/cw-orch-mock/tests/instantiate2.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::instantiate2_address; 2 | use cosmwasm_std::Api; 3 | use cosmwasm_std::Binary; 4 | use cw_orch_core::contract::interface_traits::ContractInstance; 5 | use cw_orch_core::contract::interface_traits::CwOrchInstantiate; 6 | use cw_orch_core::contract::interface_traits::CwOrchUpload; 7 | use cw_orch_core::environment::DefaultQueriers; 8 | use cw_orch_core::environment::TxHandler; 9 | use cw_orch_core::environment::WasmQuerier; 10 | use cw_orch_mock::MockBech32; 11 | use mock_contract::InstantiateMsg; 12 | use mock_contract::MockContract; 13 | 14 | #[test] 15 | fn instantiate2() -> anyhow::Result<()> { 16 | let app = MockBech32::new("mock"); 17 | 18 | let salt = vec![12, 89, 156, 63]; 19 | let mock_contract = MockContract::new("mock-contract", app.clone()); 20 | 21 | mock_contract.upload()?; 22 | 23 | let expected_address = app.wasm_querier().instantiate2_addr( 24 | mock_contract.code_id()?, 25 | &app.sender_addr(), 26 | Binary::from(salt.clone()), 27 | )?; 28 | 29 | mock_contract.instantiate2(&InstantiateMsg {}, None, &[], Binary::new(salt.clone()))?; 30 | 31 | let addr = mock_contract.address()?; 32 | 33 | assert_eq!(addr.to_string(), expected_address); 34 | 35 | // Finally we need to make sure that the instantiate2 function also works inside contracts 36 | let canon_sender = app 37 | .app 38 | .borrow() 39 | .api() 40 | .addr_canonicalize(app.sender_addr().as_str())?; 41 | 42 | // If there is a `Invalid input: canonical address length not correct` error, that means this env doesn't work with instantiate2 correctly 43 | assert_eq!( 44 | addr.to_string(), 45 | app.app 46 | .borrow() 47 | .api() 48 | .addr_humanize(&instantiate2_address( 49 | app.app 50 | .borrow() 51 | .wrap() 52 | .query_wasm_code_info(mock_contract.code_id()?)? 53 | .checksum 54 | .as_slice(), 55 | &canon_sender, 56 | &salt 57 | )?)? 58 | .to_string() 59 | ); 60 | 61 | Ok(()) 62 | } 63 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | categories = ["development-tools"] 4 | description = "Networks library for deploying and interacting with CosmWasm smart-contracts" 5 | edition = { workspace = true } 6 | keywords = ["cosmwasm", "blockchain"] 7 | license = { workspace = true } 8 | name = "cw-orch-networks" 9 | readme = "README.md" 10 | repository = { workspace = true } 11 | version = "0.24.11" 12 | 13 | exclude = [".env"] 14 | 15 | [dependencies] 16 | cw-orch-core = { workspace = true } 17 | serde = { workspace = true } 18 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod networks; 2 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/archway.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: archway 4 | pub const ARCHWAY_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "archway", 6 | pub_address_prefix: "archway", 7 | coin_type: 118u32, 8 | }; 9 | 10 | /// Archway Docs: 11 | /// Parameters: 12 | pub const CONSTANTINE_3: ChainInfo = ChainInfo { 13 | kind: ChainKind::Testnet, 14 | chain_id: "constantine-3", 15 | gas_denom: "aconst", 16 | gas_price: 1000000000000.0, 17 | grpc_urls: &["https://grpc.constantine.archway.io:443"], 18 | network_info: ARCHWAY_NETWORK, 19 | lcd_url: Some("https://api.constantine.archway.io"), 20 | fcd_url: None, 21 | }; 22 | 23 | /// Archway Docs: 24 | /// Parameters 25 | pub const ARCHWAY_1: ChainInfo = ChainInfo { 26 | kind: ChainKind::Mainnet, 27 | chain_id: "archway-1", 28 | gas_denom: "aarch", 29 | gas_price: 1000000000000.0, 30 | grpc_urls: &["https://grpc.mainnet.archway.io:443"], 31 | network_info: ARCHWAY_NETWORK, 32 | lcd_url: Some("https://api.mainnet.archway.io"), 33 | fcd_url: None, 34 | }; 35 | // ANCHOR_END: archway 36 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/bitsong.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: bitsong 4 | pub const BITSONG_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "bitsong", 6 | pub_address_prefix: "bitsong", 7 | coin_type: 639u32, 8 | }; 9 | 10 | pub const BITSONG_2B: ChainInfo = ChainInfo { 11 | kind: ChainKind::Mainnet, 12 | chain_id: "bitsong-2b", 13 | gas_denom: "ubtsg", 14 | gas_price: 0.025, 15 | grpc_urls: &[ 16 | "http://bitsong-grpc.polkachu.com:16090", 17 | "http://grpc.explorebitsong.com:443", 18 | ], 19 | network_info: BITSONG_NETWORK, 20 | lcd_url: None, 21 | fcd_url: None, 22 | }; 23 | 24 | // pub const BOBNET: ChainInfo = ChainInfo { 25 | // kind: ChainKind::Testnet, 26 | // chain_id: "bobnet", 27 | // gas_denom: "ubtsg", 28 | // gas_price: 0.025, 29 | // grpc_urls: &["http://grpc-testnet.explorebitsong.com:443"], 30 | // network_info: BITSONG_NETWORK, 31 | // lcd_url: None, 32 | // fcd_url: None, 33 | // }; 34 | 35 | pub const LOCAL_BITSONG: ChainInfo = ChainInfo { 36 | kind: ChainKind::Local, 37 | chain_id: "localbitsong", 38 | gas_denom: "ubtsg", 39 | gas_price: 0.0026, 40 | grpc_urls: &["tcp://localhost:9094"], 41 | network_info: BITSONG_NETWORK, 42 | lcd_url: None, 43 | fcd_url: None, 44 | }; 45 | // ANCHOR_END: bitsong 46 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/cosmos.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: cosmos 4 | pub const COSMOS_HUB_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "cosmoshub", 6 | pub_address_prefix: "cosmos", 7 | coin_type: 118, 8 | }; 9 | 10 | pub const COSMOS_HUB_TESTNET: ChainInfo = ICS_TESTNET; 11 | 12 | /// Cosmos Hub Testnet 13 | /// @see https://github.com/cosmos/testnets/blob/master/interchain-security/provider/README.md 14 | /// Use the faucet here: https://faucet.polypore.xyz 15 | pub const ICS_TESTNET: ChainInfo = ChainInfo { 16 | kind: ChainKind::Testnet, 17 | chain_id: "provider", 18 | gas_denom: "uatom", 19 | gas_price: 0.01, 20 | grpc_urls: &["https://grpc-rs.cosmos.nodestake.top:443"], 21 | network_info: COSMOS_HUB_NETWORK, 22 | lcd_url: Some("https://api-rs.cosmos.nodestake.top:443"), 23 | fcd_url: None, 24 | }; 25 | 26 | // ANCHOR_END: cosmos 27 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/doravota.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // https://notional.ventures/resources/endpoints#juno 4 | 5 | // ANCHOR: juno 6 | pub const DORAVOTA_NETWORK: NetworkInfo = NetworkInfo { 7 | chain_name: "doravota", 8 | pub_address_prefix: "dora", 9 | coin_type: 118u32, 10 | }; 11 | 12 | pub const VOTA_ASH: ChainInfo = ChainInfo { 13 | kind: ChainKind::Mainnet, 14 | chain_id: "vota-ash", 15 | gas_denom: "peaka", 16 | gas_price: 100000000000f64, 17 | grpc_urls: &["https://vota-grpc.dorafactory.org:443"], 18 | network_info: DORAVOTA_NETWORK, 19 | lcd_url: None, 20 | fcd_url: None, 21 | }; 22 | 23 | pub const VOTA_TESTNET: ChainInfo = ChainInfo { 24 | kind: ChainKind::Testnet, 25 | chain_id: "vota-testnet", 26 | gas_denom: "peaka", 27 | gas_price: 100000000000f64, 28 | grpc_urls: &["https://vota-testnet-grpc.dorafactory.org:443"], 29 | network_info: DORAVOTA_NETWORK, 30 | lcd_url: None, 31 | fcd_url: None, 32 | }; 33 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/injective.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: injective 4 | pub const INJECTIVE_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "injective", 6 | pub_address_prefix: "inj", 7 | coin_type: 60u32, 8 | }; 9 | 10 | /// 11 | /// 12 | /// 13 | pub const INJECTIVE_1: ChainInfo = ChainInfo { 14 | kind: ChainKind::Mainnet, 15 | chain_id: "injective-1", 16 | gas_denom: "inj", 17 | gas_price: 500_000_000.0, 18 | grpc_urls: &["https://sentry.chain.grpc.injective.network:443"], 19 | network_info: INJECTIVE_NETWORK, 20 | lcd_url: None, 21 | fcd_url: None, 22 | }; 23 | 24 | /// 25 | /// 26 | pub const INJECTIVE_888: ChainInfo = ChainInfo { 27 | kind: ChainKind::Testnet, 28 | chain_id: "injective-888", 29 | gas_denom: "inj", 30 | gas_price: 500_000_000.0, 31 | grpc_urls: &["https://k8s.testnet.chain.grpc.injective.network:443"], 32 | network_info: INJECTIVE_NETWORK, 33 | lcd_url: None, 34 | fcd_url: None, 35 | }; 36 | // ANCHOR_END: injective 37 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/juno.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // https://notional.ventures/resources/endpoints#juno 4 | 5 | // ANCHOR: juno 6 | pub const JUNO_NETWORK: NetworkInfo = NetworkInfo { 7 | chain_name: "juno", 8 | pub_address_prefix: "juno", 9 | coin_type: 118u32, 10 | }; 11 | 12 | pub const UNI_6: ChainInfo = ChainInfo { 13 | kind: ChainKind::Testnet, 14 | chain_id: "uni-6", 15 | gas_denom: "ujunox", 16 | gas_price: 0.025, 17 | grpc_urls: &["http://juno-testnet-grpc.polkachu.com:12690"], 18 | network_info: JUNO_NETWORK, 19 | lcd_url: None, 20 | fcd_url: None, 21 | }; 22 | 23 | pub const JUNO_1: ChainInfo = ChainInfo { 24 | kind: ChainKind::Mainnet, 25 | chain_id: "juno-1", 26 | gas_denom: "ujuno", 27 | gas_price: 0.0750, 28 | grpc_urls: &["http://juno-grpc.polkachu.com:12690"], 29 | network_info: JUNO_NETWORK, 30 | lcd_url: None, 31 | fcd_url: None, 32 | }; 33 | 34 | pub const LOCAL_JUNO: ChainInfo = ChainInfo { 35 | kind: ChainKind::Local, 36 | chain_id: "testing", 37 | gas_denom: "ujunox", 38 | gas_price: 0.0, 39 | grpc_urls: &["http://localhost:9090"], 40 | network_info: JUNO_NETWORK, 41 | lcd_url: None, 42 | fcd_url: None, 43 | }; 44 | // ANCHOR_END: juno 45 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/kujira.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: kujira 4 | pub const KUJIRA_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "kujira", 6 | pub_address_prefix: "kujira", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const HARPOON_4: ChainInfo = ChainInfo { 11 | kind: ChainKind::Testnet, 12 | chain_id: "harpoon-4", 13 | gas_denom: "ukuji", 14 | gas_price: 0.025, 15 | grpc_urls: &["http://kujira-testnet-grpc.polkachu.com:11890"], 16 | network_info: KUJIRA_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | // ANCHOR_END: kujira 21 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/landslide.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: landslide 4 | pub const LANDSLIDE_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "landslide", 6 | pub_address_prefix: "wasm", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const LOCAL_LANDSLIDE: ChainInfo = ChainInfo { 11 | kind: ChainKind::Local, 12 | chain_id: "landslide-test", 13 | gas_denom: "stake", 14 | gas_price: 1_f64, 15 | grpc_urls: &["http://127.0.0.1:9090"], 16 | network_info: LANDSLIDE_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | // ANCHOR_END: landslide 22 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/migaloo.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: migaloo 4 | pub const MIGALOO_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "migaloo-1", 6 | pub_address_prefix: "migaloo", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const LOCAL_MIGALOO: ChainInfo = ChainInfo { 11 | kind: ChainKind::Local, 12 | chain_id: "migaloo-chain", 13 | gas_denom: "uwhale", 14 | gas_price: 0.1, 15 | grpc_urls: &["http://localhost:9090"], 16 | network_info: MIGALOO_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | /// 22 | pub const NARWHAL_1: ChainInfo = ChainInfo { 23 | kind: ChainKind::Testnet, 24 | chain_id: "narwhal-1", 25 | gas_denom: "uwhale", 26 | gas_price: 0.1, 27 | grpc_urls: &["migaloo-testnet-grpc.polkachu.com:20790"], 28 | network_info: MIGALOO_NETWORK, 29 | lcd_url: None, 30 | fcd_url: None, 31 | }; 32 | 33 | /// 34 | pub const MIGALOO_1: ChainInfo = ChainInfo { 35 | kind: ChainKind::Mainnet, 36 | chain_id: "migaloo-1", 37 | gas_denom: "uwhale", 38 | gas_price: 0.1, 39 | grpc_urls: &["migaloo-grpc.polkachu.com:20790"], 40 | network_info: MIGALOO_NETWORK, 41 | lcd_url: None, 42 | fcd_url: None, 43 | }; 44 | // ANCHOR_END: migaloo 45 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/neutron.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: neutron 4 | pub const NEUTRON_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "neutron", 6 | pub_address_prefix: "neutron", 7 | coin_type: 118u32, 8 | }; 9 | 10 | /// 11 | pub const PION_1: ChainInfo = ChainInfo { 12 | kind: ChainKind::Testnet, 13 | chain_id: "pion-1", 14 | gas_denom: "untrn", 15 | gas_price: 0.075, 16 | grpc_urls: &["http://grpc-palvus.pion-1.ntrn.tech:80"], 17 | network_info: NEUTRON_NETWORK, 18 | lcd_url: Some("https://rest-palvus.pion-1.ntrn.tech"), 19 | fcd_url: None, 20 | }; 21 | 22 | /// 23 | pub const NEUTRON_1: ChainInfo = ChainInfo { 24 | kind: ChainKind::Mainnet, 25 | chain_id: "neutron-1", 26 | gas_denom: "untrn", 27 | gas_price: 0.075, 28 | grpc_urls: &["http://grpc-kralum.neutron-1.neutron.org:80"], 29 | network_info: NEUTRON_NETWORK, 30 | lcd_url: Some("https://rest-kralum.neutron-1.neutron.org"), 31 | fcd_url: None, 32 | }; 33 | 34 | pub const LOCAL_NEUTRON: ChainInfo = ChainInfo { 35 | kind: ChainKind::Local, 36 | chain_id: "test-1", 37 | gas_denom: "untrn", 38 | gas_price: 0.0025, 39 | grpc_urls: &["http://localhost:8090"], 40 | network_info: NEUTRON_NETWORK, 41 | lcd_url: None, 42 | fcd_url: None, 43 | }; 44 | // ANCHOR_END: neutron 45 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/nibiru.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: nibiru 4 | pub const NIBIRU_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "nibiru", 6 | pub_address_prefix: "nibi", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const NIBIRU_ITN_2: ChainInfo = ChainInfo { 11 | kind: ChainKind::Testnet, 12 | chain_id: "nibiru-itn-2", 13 | gas_denom: "unibi", 14 | gas_price: 0.025, 15 | grpc_urls: &["https://nibiru-testnet.grpc.kjnodes.com:443"], 16 | network_info: NIBIRU_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | // ANCHOR_END: nibiru 21 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/osmosis.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: osmosis 4 | pub const OSMO_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "osmosis", 6 | pub_address_prefix: "osmo", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const OSMOSIS_1: ChainInfo = ChainInfo { 11 | kind: ChainKind::Mainnet, 12 | chain_id: "osmosis-1", 13 | gas_denom: "uosmo", 14 | gas_price: 0.025, 15 | grpc_urls: &["https://grpc.osmosis.zone:443"], 16 | network_info: OSMO_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | pub const OSMO_5: ChainInfo = ChainInfo { 22 | kind: ChainKind::Testnet, 23 | chain_id: "osmo-test-5", 24 | gas_denom: "uosmo", 25 | gas_price: 0.025, 26 | grpc_urls: &["https://grpc.osmotest5.osmosis.zone:443"], 27 | network_info: OSMO_NETWORK, 28 | lcd_url: None, 29 | fcd_url: None, 30 | }; 31 | 32 | pub const LOCAL_OSMO: ChainInfo = ChainInfo { 33 | kind: ChainKind::Local, 34 | chain_id: "localosmosis", 35 | gas_denom: "uosmo", 36 | gas_price: 0.0026, 37 | grpc_urls: &["http://65.108.235.46:9094"], 38 | network_info: OSMO_NETWORK, 39 | lcd_url: None, 40 | fcd_url: None, 41 | }; 42 | // ANCHOR_END: osmosis 43 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/rollkit.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: rollkit 4 | pub const ROLLKIT_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "rollkit", 6 | pub_address_prefix: "wasm", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const LOCAL_ROLLKIT: ChainInfo = ChainInfo { 11 | kind: ChainKind::Local, 12 | chain_id: "celeswasm", 13 | gas_denom: "uwasm", 14 | gas_price: 0.025, 15 | grpc_urls: &["http://localhost:9290"], 16 | network_info: ROLLKIT_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | pub const ROLLKIT_TESTNET: ChainInfo = ChainInfo { 22 | kind: ChainKind::Local, 23 | chain_id: "rosm", 24 | gas_denom: "urosm", 25 | gas_price: 0.025, 26 | grpc_urls: &["http://grpc.rosm.rollkit.dev:9290"], 27 | network_info: ROLLKIT_NETWORK, 28 | lcd_url: None, 29 | fcd_url: None, 30 | }; 31 | // ANCHOR_END: rollkit 32 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/sei.rs: -------------------------------------------------------------------------------- 1 | use crate::networks::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: sei 4 | pub const SEI_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "sei", 6 | pub_address_prefix: "sei", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const LOCAL_SEI: ChainInfo = ChainInfo { 11 | kind: ChainKind::Local, 12 | chain_id: "sei-chain", 13 | gas_denom: "usei", 14 | gas_price: 0.1, 15 | grpc_urls: &["http://localhost:9090"], 16 | network_info: SEI_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | pub const SEI_DEVNET_3: ChainInfo = ChainInfo { 22 | kind: ChainKind::Testnet, 23 | chain_id: "sei-devnet-3", 24 | gas_denom: "usei", 25 | gas_price: 0.1, 26 | grpc_urls: &["http://sei_devnet-testnet-grpc.polkachu.com:11990"], 27 | network_info: SEI_NETWORK, 28 | lcd_url: None, 29 | fcd_url: None, 30 | }; 31 | 32 | pub const ATLANTIC_2: ChainInfo = ChainInfo { 33 | kind: ChainKind::Testnet, 34 | chain_id: "atlantic-2", 35 | gas_denom: "usei", 36 | gas_price: 0.1, 37 | grpc_urls: &["http://sei-testnet-grpc.polkachu.com:11990"], 38 | network_info: SEI_NETWORK, 39 | lcd_url: None, 40 | fcd_url: None, 41 | }; 42 | 43 | pub const PACIFIC_1: ChainInfo = ChainInfo { 44 | kind: ChainKind::Mainnet, 45 | chain_id: "pacific-1", 46 | gas_denom: "usei", 47 | gas_price: 0.1, 48 | grpc_urls: &["http://sei-grpc.polkachu.com:11990"], 49 | network_info: SEI_NETWORK, 50 | lcd_url: None, 51 | fcd_url: None, 52 | }; 53 | // ANCHOR_END: sei 54 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/terra.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: terra 4 | pub const TERRA_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "terra2", 6 | pub_address_prefix: "terra", 7 | coin_type: 330u32, 8 | }; 9 | 10 | /// Terra testnet network. 11 | /// 12 | pub const PISCO_1: ChainInfo = ChainInfo { 13 | kind: ChainKind::Testnet, 14 | chain_id: "pisco-1", 15 | gas_denom: "uluna", 16 | gas_price: 0.015, 17 | grpc_urls: &["http://terra-testnet-grpc.polkachu.com:11790"], 18 | network_info: TERRA_NETWORK, 19 | lcd_url: None, 20 | fcd_url: None, 21 | }; 22 | 23 | /// Terra mainnet network. 24 | /// 25 | pub const PHOENIX_1: ChainInfo = ChainInfo { 26 | kind: ChainKind::Mainnet, 27 | chain_id: "phoenix-1", 28 | gas_denom: "uluna", 29 | gas_price: 0.015, 30 | grpc_urls: &["http://terra-grpc.polkachu.com:11790"], 31 | network_info: TERRA_NETWORK, 32 | lcd_url: None, 33 | fcd_url: None, 34 | }; 35 | 36 | /// Terra local network. 37 | /// 38 | pub const LOCAL_TERRA: ChainInfo = ChainInfo { 39 | kind: ChainKind::Local, 40 | chain_id: "localterra", 41 | gas_denom: "uluna", 42 | gas_price: 0.15, 43 | grpc_urls: &["http://localhost:9090"], 44 | network_info: TERRA_NETWORK, 45 | lcd_url: None, 46 | fcd_url: None, 47 | }; 48 | // ANCHOR_END: terra 49 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/union.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: union 4 | pub const UNION_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "union", 6 | pub_address_prefix: "union", 7 | coin_type: 118, 8 | }; 9 | 10 | pub const UNION_TESTNET: ChainInfo = UNION_TESTNET_9; 11 | 12 | #[deprecated] 13 | pub const UNION_TESTNET_8: ChainInfo = ChainInfo { 14 | kind: ChainKind::Testnet, 15 | chain_id: "union-testnet-8", 16 | gas_denom: "muno", 17 | gas_price: 0.000025, 18 | grpc_urls: &["https://grpc.testnet-8.union.build:443"], 19 | network_info: UNION_NETWORK, 20 | lcd_url: None, 21 | fcd_url: None, 22 | }; 23 | 24 | pub const UNION_TESTNET_9: ChainInfo = ChainInfo { 25 | kind: ChainKind::Testnet, 26 | chain_id: "union-testnet-9", 27 | gas_denom: "muno", 28 | gas_price: 0.000025, 29 | grpc_urls: &[ 30 | "https://grpc.testnet-9.union.build:443", 31 | "https://grpc.union-testnet-9.cor.systems:443", 32 | ], 33 | network_info: UNION_NETWORK, 34 | lcd_url: None, 35 | fcd_url: None, 36 | }; 37 | 38 | // ANCHOR_END: union 39 | -------------------------------------------------------------------------------- /packages/cw-orch-networks/src/networks/xion.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ChainInfo, ChainKind, NetworkInfo}; 2 | 3 | // ANCHOR: xion 4 | pub const XION_NETWORK: NetworkInfo = NetworkInfo { 5 | chain_name: "xion", 6 | pub_address_prefix: "xion", 7 | coin_type: 118u32, 8 | }; 9 | 10 | pub const XION_TESTNET_1: ChainInfo = ChainInfo { 11 | kind: ChainKind::Testnet, 12 | chain_id: "xion-testnet-1", 13 | gas_denom: "uxion", 14 | gas_price: 0.001, 15 | grpc_urls: &["http://xion-testnet-grpc.polkachu.com:22390"], 16 | network_info: XION_NETWORK, 17 | lcd_url: None, 18 | fcd_url: None, 19 | }; 20 | 21 | pub const XION_TESTNET_2: ChainInfo = ChainInfo { 22 | kind: ChainKind::Testnet, 23 | chain_id: "xion-testnet-2", 24 | gas_denom: "uxion", 25 | gas_price: 0.001, 26 | grpc_urls: &["https://grpc.xion-testnet-2.burnt.com:443"], 27 | network_info: XION_NETWORK, 28 | lcd_url: None, 29 | fcd_url: None, 30 | }; 31 | 32 | pub const XION_MAINNET_1: ChainInfo = ChainInfo { 33 | kind: ChainKind::Mainnet, 34 | chain_id: "xion-mainnet-1", 35 | gas_denom: "uxion", 36 | gas_price: 0.001, 37 | grpc_urls: &["https://grpc.xion-mainnet-1.burnt.com:443"], 38 | network_info: XION_NETWORK, 39 | lcd_url: None, 40 | fcd_url: None, 41 | }; 42 | 43 | // ANCHOR_END: xion 44 | -------------------------------------------------------------------------------- /packages/cw-orch-neutron-test-tube/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Cw-orch environment adapter for neutron-test-tube" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-neutron-test-tube" 7 | repository.workspace = true 8 | version = "0.2.2" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | 14 | # Test Tube env deps 15 | neutron-test-tube = { workspace = true } 16 | 17 | cosmwasm-std = { workspace = true } 18 | cw-orch-core = { workspace = true } 19 | cw-orch-mock = { workspace = true } 20 | cw-orch-traits = { workspace = true } 21 | prost = { workspace = true } 22 | prost-types = { workspace = true } 23 | serde = { workspace = true } 24 | 25 | [dev-dependencies] 26 | counter-contract = { path = "../../contracts-ws/contracts/counter" } 27 | env_logger = "0.11.3" 28 | 29 | cw-orch = { workspace = true } 30 | -------------------------------------------------------------------------------- /packages/cw-orch-neutron-test-tube/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Integration testing execution environment backed by a [neutron-test-tube](neutron_test_tube) App. 2 | //! It has an associated state that stores deployment information for easy retrieval and contract interactions. 3 | mod core; 4 | 5 | mod queriers; 6 | pub use self::core::*; 7 | -------------------------------------------------------------------------------- /packages/cw-orch-neutron-test-tube/src/queriers/env.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ 2 | EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, 3 | }; 4 | 5 | use crate::NeutronTestTube; 6 | 7 | impl EnvironmentQuerier for NeutronTestTube { 8 | fn env_info(&self) -> EnvironmentInfo { 9 | let block = self.block_info().unwrap(); 10 | let chain_id = block.chain_id; 11 | let chain_name = chain_id.rsplitn(2, '-').collect::>()[1].to_string(); 12 | 13 | EnvironmentInfo { 14 | chain_id, 15 | chain_name, 16 | deployment_id: "default".to_string(), 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/cw-orch-neutron-test-tube/src/queriers/mod.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::{ 2 | environment::{DefaultQueriers, QueryHandler, StateInterface}, 3 | CwEnvError, 4 | }; 5 | 6 | use super::NeutronTestTube; 7 | 8 | pub mod bank; 9 | mod env; 10 | pub mod node; 11 | pub mod wasm; 12 | 13 | impl QueryHandler for NeutronTestTube { 14 | type Error = CwEnvError; 15 | 16 | fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { 17 | self.wait_seconds(amount * 10) 18 | } 19 | 20 | fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { 21 | self.app.borrow().increase_time(secs); 22 | Ok(()) 23 | } 24 | 25 | fn next_block(&self) -> Result<(), CwEnvError> { 26 | self.wait_blocks(1) 27 | } 28 | } 29 | 30 | impl DefaultQueriers for NeutronTestTube { 31 | type Bank = bank::NeutronTestTubeBankQuerier; 32 | type Wasm = wasm::NeutronTestTubeWasmQuerier; 33 | type Node = node::NeutronTestTubeNodeQuerier; 34 | } 35 | -------------------------------------------------------------------------------- /packages/cw-orch-neutron-test-tube/src/queriers/node.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use crate::NeutronTestTube; 4 | use cosmwasm_std::{BlockInfo, Timestamp}; 5 | use cw_orch_core::{ 6 | environment::{NodeQuerier, Querier, QuerierGetter, StateInterface}, 7 | CwEnvError, 8 | }; 9 | use cw_orch_mock::cw_multi_test::AppResponse; 10 | use neutron_test_tube::NeutronTestApp; 11 | 12 | pub struct NeutronTestTubeNodeQuerier { 13 | app: Rc>, 14 | } 15 | 16 | impl NeutronTestTubeNodeQuerier { 17 | fn new(mock: &NeutronTestTube) -> Self { 18 | Self { 19 | app: mock.app.clone(), 20 | } 21 | } 22 | } 23 | 24 | impl Querier for NeutronTestTubeNodeQuerier { 25 | type Error = CwEnvError; 26 | } 27 | 28 | impl QuerierGetter for NeutronTestTube { 29 | fn querier(&self) -> NeutronTestTubeNodeQuerier { 30 | NeutronTestTubeNodeQuerier::new(self) 31 | } 32 | } 33 | 34 | impl NodeQuerier for NeutronTestTubeNodeQuerier { 35 | type Response = AppResponse; 36 | fn latest_block(&self) -> Result { 37 | Ok(BlockInfo { 38 | chain_id: "neutron-1".to_string(), 39 | height: self.block_height()?, 40 | time: Timestamp::from_nanos(self.block_time()?.try_into().unwrap()), 41 | }) 42 | } 43 | 44 | fn block_by_height(&self, _height: u64) -> Result { 45 | unimplemented!() 46 | } 47 | 48 | fn block_height(&self) -> Result { 49 | Ok(self.app.borrow().get_block_height().try_into().unwrap()) 50 | } 51 | 52 | fn block_time(&self) -> Result { 53 | Ok(self.app.borrow().get_block_time_nanos().try_into().unwrap()) 54 | } 55 | 56 | fn simulate_tx(&self, _tx_bytes: Vec) -> Result { 57 | unimplemented!() 58 | } 59 | 60 | fn find_tx(&self, _hash: String) -> Result { 61 | unimplemented!() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/cw-orch-osmosis-test-tube/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Cw-orch environment adapter for osmosis-test-tube" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-osmosis-test-tube" 7 | repository.workspace = true 8 | version = "0.5.1" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | 14 | # Test Tube env deps 15 | cosmwasm-std = { workspace = true } 16 | cw-orch-core = { workspace = true } 17 | cw-orch-mock = { workspace = true } 18 | cw-orch-traits = { workspace = true } 19 | osmosis-test-tube = { workspace = true } 20 | prost = { workspace = true } 21 | prost-types = { workspace = true } 22 | serde = { workspace = true } 23 | 24 | [dev-dependencies] 25 | counter-contract = { path = "../../contracts-ws/contracts/counter" } 26 | env_logger = "0.11.3" 27 | 28 | cw-orch = { workspace = true } 29 | -------------------------------------------------------------------------------- /packages/cw-orch-osmosis-test-tube/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Integration testing execution environment backed by a [osmosis-test-tube](osmosis_test_tube) App. 2 | //! It has an associated state that stores deployment information for easy retrieval and contract interactions. 3 | mod core; 4 | 5 | mod queriers; 6 | pub use self::core::*; 7 | -------------------------------------------------------------------------------- /packages/cw-orch-osmosis-test-tube/src/queriers/env.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::{ 2 | EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, 3 | }; 4 | 5 | use crate::OsmosisTestTube; 6 | 7 | impl EnvironmentQuerier for OsmosisTestTube { 8 | fn env_info(&self) -> EnvironmentInfo { 9 | let block = self.block_info().unwrap(); 10 | let chain_id = block.chain_id; 11 | let chain_name = chain_id.rsplitn(2, '-').collect::>()[1].to_string(); 12 | 13 | EnvironmentInfo { 14 | chain_id, 15 | chain_name, 16 | deployment_id: "default".to_string(), 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/cw-orch-osmosis-test-tube/src/queriers/mod.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::{ 2 | environment::{DefaultQueriers, QueryHandler, StateInterface}, 3 | CwEnvError, 4 | }; 5 | 6 | use super::OsmosisTestTube; 7 | 8 | pub mod bank; 9 | mod env; 10 | pub mod node; 11 | pub mod wasm; 12 | 13 | impl QueryHandler for OsmosisTestTube { 14 | type Error = CwEnvError; 15 | 16 | fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { 17 | self.wait_seconds(amount * 10) 18 | } 19 | 20 | fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { 21 | self.app.borrow().increase_time(secs); 22 | Ok(()) 23 | } 24 | 25 | fn next_block(&self) -> Result<(), CwEnvError> { 26 | self.wait_blocks(1) 27 | } 28 | } 29 | 30 | impl DefaultQueriers for OsmosisTestTube { 31 | type Bank = bank::OsmosisTestTubeBankQuerier; 32 | type Wasm = wasm::OsmosisTestTubeWasmQuerier; 33 | type Node = node::OsmosisTestTubeNodeQuerier; 34 | } 35 | -------------------------------------------------------------------------------- /packages/cw-orch-osmosis-test-tube/src/queriers/node.rs: -------------------------------------------------------------------------------- 1 | use std::{cell::RefCell, rc::Rc}; 2 | 3 | use crate::OsmosisTestTube; 4 | use cosmwasm_std::{BlockInfo, Timestamp}; 5 | use cw_orch_core::{ 6 | environment::{NodeQuerier, Querier, QuerierGetter, StateInterface}, 7 | CwEnvError, 8 | }; 9 | use cw_orch_mock::cw_multi_test::AppResponse; 10 | use osmosis_test_tube::OsmosisTestApp; 11 | 12 | pub struct OsmosisTestTubeNodeQuerier { 13 | app: Rc>, 14 | } 15 | 16 | impl OsmosisTestTubeNodeQuerier { 17 | fn new(mock: &OsmosisTestTube) -> Self { 18 | Self { 19 | app: mock.app.clone(), 20 | } 21 | } 22 | } 23 | 24 | impl Querier for OsmosisTestTubeNodeQuerier { 25 | type Error = CwEnvError; 26 | } 27 | 28 | impl QuerierGetter for OsmosisTestTube { 29 | fn querier(&self) -> OsmosisTestTubeNodeQuerier { 30 | OsmosisTestTubeNodeQuerier::new(self) 31 | } 32 | } 33 | 34 | impl NodeQuerier for OsmosisTestTubeNodeQuerier { 35 | type Response = AppResponse; 36 | fn latest_block(&self) -> Result { 37 | Ok(BlockInfo { 38 | chain_id: "osmosis-1".to_string(), 39 | height: self.block_height()?, 40 | time: Timestamp::from_nanos(self.block_time()?.try_into().unwrap()), 41 | }) 42 | } 43 | 44 | fn block_by_height(&self, _height: u64) -> Result { 45 | unimplemented!() 46 | } 47 | 48 | fn block_height(&self) -> Result { 49 | Ok(self.app.borrow().get_block_height().try_into().unwrap()) 50 | } 51 | 52 | fn block_time(&self) -> Result { 53 | Ok(self.app.borrow().get_block_time_nanos().try_into().unwrap()) 54 | } 55 | 56 | fn simulate_tx(&self, _tx_bytes: Vec) -> Result { 57 | unimplemented!() 58 | } 59 | 60 | fn find_tx(&self, _hash: String) -> Result { 61 | unimplemented!() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/cw-orch-traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | categories = ["development-tools"] 4 | description = "Scripting library for deploying and interacting with CosmWasm smart-contracts" 5 | edition = { workspace = true } 6 | keywords = ["cosmwasm", "blockchain"] 7 | license = { workspace = true } 8 | name = "cw-orch-traits" 9 | readme = "README.md" 10 | repository = { workspace = true } 11 | version = "0.25.0" 12 | 13 | 14 | [dependencies] 15 | cw-orch-core = { workspace = true } 16 | prost-types = { workspace = true } 17 | -------------------------------------------------------------------------------- /packages/cw-orch-traits/README.md: -------------------------------------------------------------------------------- 1 | This packages is used by cw-orchestrator to add additional functionalities on CwEnv (environments) in order to make the different execution environments even more compatible with each other and standardized. 2 | 3 | The FullNode trait is used as a alias for structures that implement all the traits in this package. -------------------------------------------------------------------------------- /packages/cw-orch-traits/src/lib.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::CwEnv; 2 | 3 | pub mod stargate; 4 | 5 | pub use stargate::Stargate; 6 | 7 | pub trait FullNode: CwEnv + Stargate {} 8 | 9 | impl FullNode for C {} 10 | -------------------------------------------------------------------------------- /packages/cw-orch-traits/src/stargate.rs: -------------------------------------------------------------------------------- 1 | use cw_orch_core::environment::TxHandler; 2 | use prost_types::Any; 3 | 4 | /// Alows the execution of stargate like messages on cw-orch environments 5 | pub trait Stargate: TxHandler { 6 | /// Execute a custom abci/starship message on the environment 7 | /// The message should already be encoded as protobuf any 8 | fn commit_any( 9 | &self, 10 | msgs: Vec, 11 | memo: Option<&str>, 12 | ) -> Result<::Response, ::Error>; 13 | } 14 | -------------------------------------------------------------------------------- /packages/integrations/cw-plus/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "cw-orch interfaces for cw-plus base contracts" 3 | documentation = "https://orchestrator.abstract.money" 4 | edition = "2021" 5 | homepage = "https://abstract.money" 6 | license = "Apache-2.0" 7 | name = "cw-plus-orch" 8 | repository = "https://github.com/AbstractSDK/cw-orchestrator" 9 | version = "0.25.0" # Version of cw-orch that's used 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [dependencies] 14 | cosmwasm-schema = { version = "2.0.0" } 15 | cosmwasm-std = { workspace = true } 16 | cw-utils = { workspace = true } 17 | 18 | 19 | cw-controllers = { version = "2.0.0" } 20 | cw1 = { version = "2.0.0" } 21 | cw1-subkeys = { version = "2.0.0", features = ["library"] } 22 | cw1-whitelist = { version = "2.0.0", features = ["library"] } 23 | cw20 = { version = "2.0.0" } 24 | cw20-base = { version = "2.0.0", features = ["library"] } 25 | cw20-ics20 = { version = "2.0.0", features = ["library"] } 26 | cw3 = { version = "2.0.0" } 27 | cw3-fixed-multisig = { version = "2.0.0", features = ["library"] } 28 | cw3-flex-multisig = { version = "2.0.0", features = ["library"] } 29 | cw4 = { version = "2.0.0" } 30 | cw4-group = { version = "2.0.0", features = ["library"] } 31 | cw4-stake = { version = "2.0.0", features = ["library"] } 32 | 33 | cw-orch-from-interface-derive = { version = "0.1.0", path = "../../macros/from-interface-derive" } 34 | 35 | cw-orch = { workspace = true } 36 | 37 | [dev-dependencies] 38 | cw-orch = { workspace = true, features = ["daemon"] } 39 | cw-orch-interchain = { workspace = true } 40 | dotenv = "0.15.0" 41 | octocrab = "0.39.0" 42 | pretty_env_logger = "0.5.0" 43 | reqwest = "0.12.7" 44 | tokio.workspace = true 45 | -------------------------------------------------------------------------------- /packages/integrations/cw-plus/examples/download_wasms.rs: -------------------------------------------------------------------------------- 1 | use cw_orch::anyhow; 2 | use std::{io::Cursor, path::PathBuf, str::FromStr}; 3 | 4 | pub const CW_PLUS_REPO_OWNER: &str = "CosmWasm"; 5 | pub const CW_PLUS_REPO_NAME: &str = "cw-plus"; 6 | pub const CW_PLUS_RELEASE_TAG: &str = "v2.0.0"; 7 | 8 | pub const ALL_CONTRACTS: &[&str] = &[ 9 | "cw1_subkeys", 10 | "cw1_whitelist", 11 | "cw3_fixed_multisig", 12 | "cw3_flex_multisig", 13 | "cw4_group", 14 | "cw4_stake", 15 | "cw20_base", 16 | "cw20_ics20", 17 | ]; 18 | 19 | #[tokio::main] 20 | async fn main() -> anyhow::Result<()> { 21 | let crate_dir = env!("CARGO_MANIFEST_DIR"); 22 | let artifacts_dir = PathBuf::from_str(crate_dir)?.join("artifacts"); 23 | 24 | // We create the artifacts directory if non-existent 25 | std::fs::create_dir_all(&artifacts_dir)?; 26 | 27 | // We get the release, common for all artifacts 28 | let release = octocrab::instance() 29 | .repos(CW_PLUS_REPO_OWNER, CW_PLUS_REPO_NAME) 30 | .releases() 31 | .get_by_tag(CW_PLUS_RELEASE_TAG) 32 | .await?; 33 | 34 | for contract in ALL_CONTRACTS { 35 | let release_file_name = format!("{contract}.wasm"); 36 | let file_name = artifacts_dir.join(&release_file_name); 37 | 38 | let wasm_asset = release 39 | .assets 40 | .iter() 41 | .find(|asset| asset.name.eq(&release_file_name)) 42 | .unwrap(); 43 | 44 | let response = reqwest::get(wasm_asset.browser_download_url.clone()).await?; 45 | let mut file = std::fs::File::create(file_name)?; 46 | let mut content = Cursor::new(response.bytes().await?); 47 | std::io::copy(&mut content, &mut file)?; 48 | } 49 | Ok(()) 50 | } 51 | -------------------------------------------------------------------------------- /packages/integrations/cw-plus/examples/test_wasm.rs: -------------------------------------------------------------------------------- 1 | use cw_orch::daemon::networks::LOCAL_JUNO; 2 | use cw_orch::prelude::*; 3 | use cw_plus_orch::cw1_subkeys::Cw1SubKeys; 4 | use cw_plus_orch::cw1_whitelist::Cw1Whitelist; 5 | use cw_plus_orch::cw20_base::Cw20Base; 6 | use cw_plus_orch::cw20_ics20::Cw20Ics20; 7 | use cw_plus_orch::cw3_fixed_multisig::Cw3FixedMultisig; 8 | use cw_plus_orch::cw3_flex_multisig::Cw3FlexMultisig; 9 | use cw_plus_orch::cw4_group::Cw4Group; 10 | use cw_plus_orch::cw4_stake::Cw4Stake; 11 | 12 | fn main() -> cw_orch::anyhow::Result<()> { 13 | dotenv::dotenv()?; 14 | pretty_env_logger::init(); 15 | 16 | let daemon = Daemon::builder(LOCAL_JUNO).build()?; 17 | 18 | Cw1SubKeys::new("cw1_subkeys", daemon.clone()).upload()?; 19 | Cw1Whitelist::new("cw1_whitelist", daemon.clone()).upload()?; 20 | Cw3FixedMultisig::new("cw3_fixed_multisig", daemon.clone()).upload()?; 21 | Cw3FlexMultisig::new("cw3_flex_multisig", daemon.clone()).upload()?; 22 | Cw4Group::new("cw4_group", daemon.clone()).upload()?; 23 | Cw4Stake::new("cw4_stake", daemon.clone()).upload()?; 24 | Cw20Base::new("cw20_base", daemon.clone()).upload()?; 25 | Cw20Ics20::new("cw20_ics20", daemon.clone()).upload()?; 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /packages/integrations/cw-plus/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cw1_subkeys; 2 | pub mod cw1_whitelist; 3 | pub mod cw20_base; 4 | pub mod cw20_ics20; 5 | pub mod cw3_fixed_multisig; 6 | pub mod cw3_flex_multisig; 7 | pub mod cw4_group; 8 | pub mod cw4_stake; 9 | 10 | pub const WASM_RELEASE_TAG: &str = "v1.1.2"; 11 | pub const WASM_REPO_OWNER: &str = "cosmwasm"; 12 | pub const WASM_REPO_NAME: &str = "cw-plus"; 13 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Interchain extension for cw-orch. Creates the basic traits for working with interchain environments" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-interchain-core" 7 | repository.workspace = true 8 | version = "0.9.2" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [features] 13 | daemon = ["dep:cw-orch-daemon"] 14 | 15 | 16 | [dependencies] 17 | base64 = "0.22.1" 18 | cosmwasm-schema = "2.1.3" 19 | cosmwasm-std = { workspace = true } 20 | cw-orch-core = { workspace = true } 21 | cw-orch-daemon = { workspace = true, optional = true } 22 | cw-orch-mock = { workspace = true } 23 | futures = "0.3.30" 24 | ibc-relayer-types = { workspace = true } 25 | log = { workspace = true } 26 | # TODO: polytone = "2.0.0" 27 | prost = "0.13.1" 28 | serde = { workspace = true } 29 | serde_json = { workspace = true } 30 | thiserror = { workspace = true } 31 | tokio = "1.39.2" 32 | tonic = { workspace = true, features = ["tls", "tls-roots"] } 33 | 34 | [dev-dependencies] 35 | cosmos-sdk-proto = { workspace = true } 36 | counter-contract = { path = "../../../contracts-ws/contracts/counter" } 37 | cw-orch = { workspace = true } 38 | cw-orch-interchain = { path = "../../../cw-orch-interchain", features = ["daemon"] } 39 | ibc-proto = { workspace = true } 40 | prost-types = { workspace = true } 41 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/src/error.rs: -------------------------------------------------------------------------------- 1 | //! Generic Error type for interchain errors 2 | 3 | #![allow(missing_docs)] 4 | use cosmwasm_std::{Binary, StdError}; 5 | use ibc_relayer_types::core::ics24_host::error::ValidationError; 6 | use thiserror::Error; 7 | 8 | use cw_orch_core::CwEnvError; 9 | 10 | #[derive(Error, Debug)] 11 | pub enum InterchainError { 12 | #[error("{0}")] 13 | GenericError(String), 14 | 15 | #[error(transparent)] 16 | CwOrchError(#[from] CwEnvError), 17 | 18 | #[error(transparent)] 19 | StdError(#[from] StdError), 20 | 21 | #[error("Error validating IBC structures {0}")] 22 | ValidationError(#[from] ValidationError), 23 | 24 | #[error("Error validating IBC structures {0}")] 25 | ICSChannel(#[from] ibc_relayer_types::core::ics04_channel::error::Error), 26 | 27 | #[error("Could not find hermes container. Ensure it is running.")] 28 | HermesContainerNotFound, 29 | 30 | #[error("daemon for chain {0} not found")] 31 | DaemonNotFound(String), 32 | 33 | #[error("chain config for chain {0} not found")] 34 | ChainConfigNotFound(String), 35 | 36 | #[error("Configuration already registered for chain {0}")] 37 | AlreadyRegistered(String), 38 | 39 | #[error("Chain `{0}` not found in the interchain environment. Please register it before analyzing transactions")] 40 | ChainNotFound(String), 41 | 42 | #[error("Packet relaying failed, timeout received")] 43 | PacketTimeout {}, 44 | 45 | #[error( 46 | "Acknowledgement decoding failed with ack: {0:x?}, tried decoding it as json : {1:x?}. Try using `assert_custom` instead !" 47 | )] 48 | AckDecodingFailed(Binary, String), 49 | 50 | #[error("No matching packets were found matching the given parsing function")] 51 | NoMatchingPacketFound(), 52 | 53 | #[error("Some packets were not parsed by the given parsing functions")] 54 | RemainingPackets {}, 55 | 56 | #[error("No packets were found while following packets")] 57 | NoPacketsFound {}, 58 | 59 | #[error("Failure acknowledgment received: {0:?}")] 60 | FailedAckReceived(String), 61 | 62 | #[error("Callback Failure during acknowledgment : {0:?}")] 63 | CallbackError(String), 64 | } 65 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/src/ibc_query.rs: -------------------------------------------------------------------------------- 1 | use crate::results::NetworkId; 2 | use cosmwasm_std::Api; 3 | use cw_orch_core::environment::CwEnv; 4 | use cw_orch_core::environment::QueryHandler; 5 | use cw_orch_mock::{MockBase, MockState}; 6 | 7 | /// Adds additional capabilities to CwEnv for use with ibc environments 8 | pub trait IbcQueryHandler: CwEnv { 9 | /// Query handler for the environment 10 | /// This should allow users to query anything related to IBC functionalities on the environment (if possible) 11 | type Handler: Clone + Send + Sync; 12 | 13 | /// Returns the `IbcQueryHandler::Handler` associated with the environment 14 | fn ibc_handler(&self) -> Self::Handler; 15 | 16 | /// Returns the chain id of the environment (for ibc identification purposes) 17 | fn chain_id(&self) -> NetworkId; 18 | } 19 | 20 | #[cfg(feature = "daemon")] 21 | // Temporary until we can actually push to cw-orch-daemon 22 | impl IbcQueryHandler for cw_orch_daemon::Daemon { 23 | type Handler = tonic::transport::Channel; 24 | 25 | fn ibc_handler(&self) -> tonic::transport::Channel { 26 | self.channel() 27 | } 28 | 29 | fn chain_id(&self) -> NetworkId { 30 | use cw_orch_core::environment::ChainState; 31 | 32 | self.state().chain_data.chain_id.to_string() 33 | } 34 | } 35 | 36 | // Temporary until we can actually push to cw-orch-mock 37 | impl IbcQueryHandler for MockBase { 38 | type Handler = (); 39 | fn ibc_handler(&self) {} 40 | 41 | fn chain_id(&self) -> NetworkId { 42 | self.block_info().unwrap().chain_id 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate aims at providing types, structures and traits for implementing an IBC execution/analysis environment 2 | //! It provides helpers and a common structure to make the code as environment agnostic as possible 3 | //! Just like cw-orch as a whole it aims at unifying the developer experience inside tests/scripts/maintenance processes. 4 | 5 | #![warn(missing_docs)] 6 | pub mod channel; 7 | 8 | /// Contains definitions of the main trait exposed by this crate 9 | pub mod env; 10 | 11 | /// Contains default acknowledgment parsers 12 | mod ack_parser; 13 | mod error; 14 | 15 | pub(crate) mod analysis; 16 | pub(crate) mod ibc_query; 17 | pub(crate) mod packet; 18 | /// Type definition for interchain structure and return types 19 | pub mod results; 20 | pub(crate) mod tx; 21 | 22 | pub use ack_parser::IbcAckParser; 23 | pub use analysis::PacketAnalysis; 24 | pub use env::{contract_port, InterchainEnv}; 25 | pub use error::InterchainError; 26 | pub use ibc_query::IbcQueryHandler; 27 | pub use packet::{ 28 | success::{IbcAppResult, IbcPacketResult, SuccessNestedPacketsFlow, SuccessSinglePacketFlow}, 29 | IbcPacketInfo, IbcPacketOutcome, NestedPacketsFlow, SinglePacketFlow, 30 | }; 31 | pub use tx::TxId; 32 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/src/results.rs: -------------------------------------------------------------------------------- 1 | use crate::ibc_query::IbcQueryHandler; 2 | use crate::packet::NestedPacketsFlow; 3 | use crate::{channel::InterchainChannel, env::ChannelCreation}; 4 | use cw_orch_core::environment::TxHandler; 5 | use ibc_relayer_types::core::ics24_host::identifier::ChannelId; 6 | 7 | /// Chain identification for cw-orch Ibc purposes 8 | pub type NetworkId = String; 9 | 10 | // Return types for the env trait 11 | /// Result returned by InterchainEnv::_internal_create_channel 12 | pub struct InternalChannelCreationResult { 13 | /// Channel creation result specific the used chain 14 | pub result: ChannelCreationResult, 15 | /// Connection id on which the channel was created. 16 | /// This connection id is supposed to be known by the channel creation environment 17 | pub src_connection_id: String, 18 | } 19 | 20 | /// Result returned by InterchainEnv::get_channel_creation_txs 21 | pub struct ChannelCreationTransactionsResult { 22 | /// Id of the channel that was just created on the src chain 23 | pub src_channel_id: ChannelId, 24 | /// Id of the channel that was just created on the dst chain 25 | pub dst_channel_id: ChannelId, 26 | /// Transactions involved in the channel creation 27 | pub channel_creation_txs: ChannelCreation<::Response>, 28 | } 29 | 30 | /// Result returned by InterchainEnv::create_channel 31 | pub struct ChannelCreationResult { 32 | /// Channel object containing every variable needed for identifying the channel that was just created 33 | pub interchain_channel: InterchainChannel<::Handler>, 34 | /// Transactions involved in the channel creation + Their packet following analysis 35 | pub channel_creation_txs: ChannelCreation>, 36 | } 37 | -------------------------------------------------------------------------------- /packages/interchain/interchain-core/src/tx.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | use cosmwasm_std::Empty; 4 | use cw_orch_core::environment::{CwEnv, IndexResponse, TxHandler}; 5 | 6 | /// Identifies a transaction 7 | #[derive(Clone)] 8 | pub struct TxId { 9 | /// Chain Id on which the transaction was broadcasted 10 | pub chain_id: String, 11 | /// Transactions response for the transaction (env specific) 12 | pub response: ::Response, 13 | 14 | _phantom_data: PhantomData, 15 | } 16 | 17 | impl TxId { 18 | /// Creates a new Tx Id object identifying a transaction exactly 19 | pub fn new(chain_id: String, response: ::Response) -> Self { 20 | TxId { 21 | chain_id, 22 | response, 23 | _phantom_data: Default::default(), 24 | } 25 | } 26 | } 27 | 28 | impl std::fmt::Debug for TxId { 29 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 30 | f.debug_struct("TxId") 31 | .field("chain_id", &self.chain_id) 32 | .field("response", &self.response) 33 | .finish() 34 | } 35 | } 36 | 37 | impl IndexResponse for TxId { 38 | fn events(&self) -> Vec { 39 | self.response.events() 40 | } 41 | 42 | fn event_attr_value( 43 | &self, 44 | event_type: &str, 45 | attr_key: &str, 46 | ) -> cosmwasm_std::StdResult { 47 | self.response.event_attr_value(event_type, attr_key) 48 | } 49 | 50 | fn event_attr_values(&self, event_type: &str, attr_key: &str) -> Vec { 51 | self.response.event_attr_values(event_type, attr_key) 52 | } 53 | 54 | fn data(&self) -> Option { 55 | self.response.data() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/interchain/interchain-daemon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "An interchain intergration crate for interacting with actual chain nodes (via gRPC)" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-interchain-daemon" 7 | repository.workspace = true 8 | version = "0.9.0" 9 | 10 | [lib] 11 | 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [dependencies] 16 | cw-orch-core = { workspace = true } 17 | cw-orch-daemon = { workspace = true } 18 | 19 | tokio = { workspace = true } 20 | 21 | async-recursion = "1.1.1" 22 | base64 = "0.22.1" 23 | cosmrs = { workspace = true } 24 | cosmwasm-schema = "2.1.3" 25 | derive_builder = "0.20.0" 26 | diff-struct = "0.5.3" 27 | futures = "0.3.30" 28 | futures-util = "0.3.30" 29 | ibc-relayer-types = { workspace = true } 30 | log = "0.4.22" 31 | log4rs = "1.3.0" 32 | serde_json = { workspace = true } 33 | thiserror = "1.0.63" 34 | tonic = { workspace = true } 35 | 36 | cosmwasm-std = { workspace = true } 37 | cw-orch-interchain-core = { workspace = true, features = ["daemon"] } 38 | cw-orch-starship = { workspace = true } 39 | dialoguer = "0.11.0" 40 | 41 | [dev-dependencies] 42 | 43 | anyhow = { workspace = true } 44 | cw-orch = { workspace = true, features = ["daemon"] } 45 | cw-orch-interchain = { path = "../../../cw-orch-interchain", features = ["daemon"] } 46 | pretty_env_logger = "0.5.0" 47 | -------------------------------------------------------------------------------- /packages/interchain/interchain-daemon/examples/starship_channel.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::IbcOrder; 2 | use cw_orch_core::environment::QuerierGetter; 3 | use cw_orch_daemon::queriers::Ibc; 4 | use cw_orch_daemon::Daemon; 5 | use cw_orch_interchain_core::{results::ChannelCreationResult, InterchainEnv}; 6 | use cw_orch_interchain_daemon::ChannelCreator; 7 | use cw_orch_starship::Starship; 8 | use ibc_relayer_types::core::ics24_host::identifier::PortId; 9 | 10 | fn assert_ordering( 11 | channel: ChannelCreationResult, 12 | juno: &Daemon, 13 | order: IbcOrder, 14 | ) -> anyhow::Result<()> { 15 | let ibc_querier: Ibc = juno.querier(); 16 | let channel = channel 17 | .interchain_channel 18 | .get_ordered_ports_from("juno-1")?; 19 | 20 | let channel_info = juno.rt_handle.block_on(ibc_querier._channel( 21 | channel.0.port.to_string(), 22 | channel.0.channel.unwrap().to_string(), 23 | ))?; 24 | match order { 25 | IbcOrder::Ordered => assert_eq!(channel_info.ordering, 2), 26 | IbcOrder::Unordered => assert_eq!(channel_info.ordering, 1), 27 | } 28 | Ok(()) 29 | } 30 | 31 | fn main() -> anyhow::Result<()> { 32 | pretty_env_logger::init(); 33 | let starship = Starship::new(None)?; 34 | let interchain_env = starship.interchain_env(); 35 | 36 | let juno = interchain_env.get_chain("juno-1")?; 37 | 38 | let channel_created = interchain_env.create_channel( 39 | "juno-1", 40 | "stargaze-1", 41 | &PortId::transfer(), 42 | &PortId::transfer(), 43 | "ics20-1", 44 | Some(IbcOrder::Unordered), 45 | )?; 46 | assert_ordering(channel_created, &juno, IbcOrder::Unordered)?; 47 | 48 | let channel_created = interchain_env.create_channel( 49 | "juno-1", 50 | "stargaze-1", 51 | &PortId::transfer(), 52 | &PortId::transfer(), 53 | "ics20-1", 54 | None, 55 | )?; 56 | assert_ordering(channel_created, &juno, IbcOrder::Unordered)?; 57 | 58 | Ok(()) 59 | } 60 | -------------------------------------------------------------------------------- /packages/interchain/interchain-daemon/src/error.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | 3 | use cosmwasm_std::StdError; 4 | use cw_orch_interchain_core::{channel::InterchainChannel, results::NetworkId, InterchainError}; 5 | use thiserror::Error; 6 | use tonic::transport::Channel; 7 | 8 | #[derive(Error, Debug)] 9 | pub enum InterchainDaemonError { 10 | #[error(transparent)] 11 | InterchainError(#[from] InterchainError), 12 | 13 | #[error(transparent)] 14 | StdError(#[from] StdError), 15 | 16 | #[error(transparent)] 17 | IoError(#[from] std::io::Error), 18 | 19 | #[error("You have interrupted the script execution")] 20 | ManualInterruption, 21 | 22 | #[error("Error interacting with starship {0}")] 23 | Starship(#[from] cw_orch_starship::client::StarshipClientError), 24 | 25 | #[error("Error interacting with daemon {0}")] 26 | Daemon(#[from] cw_orch_daemon::DaemonError), 27 | 28 | #[error("Error validating IBC structures {0}")] 29 | ValidationError(#[from] ibc_relayer_types::core::ics24_host::error::ValidationError), 30 | 31 | #[error("Error validating IBC structures {0}")] 32 | ICSChannel(#[from] ibc_relayer_types::core::ics04_channel::error::Error), 33 | 34 | #[error("Could not find hermes container. Ensure it is running.")] 35 | HermesContainerNotFound, 36 | 37 | #[error("daemon for chain {0} not found")] 38 | DaemonNotFound(String), 39 | 40 | #[error("Channel creation events not found from chain {src_chain} on following channel : {channel:?}")] 41 | ChannelCreationEventsNotFound { 42 | src_chain: NetworkId, 43 | channel: InterchainChannel, 44 | }, 45 | 46 | #[error("Configuration already registered for chain {0}")] 47 | AlreadyRegistered(String), 48 | 49 | #[error(transparent)] 50 | Dialoguer(#[from] dialoguer::Error), 51 | } 52 | 53 | // impl From 54 | impl From for InterchainError { 55 | fn from(value: InterchainDaemonError) -> Self { 56 | InterchainError::GenericError(value.to_string()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/interchain/interchain-daemon/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(missing_docs)] 2 | //! Implementation of the interchain environment for the daemon chain type. 3 | //! This also adds more helpers in the daemon case 4 | 5 | mod channel_creator; 6 | pub mod error; 7 | mod interchain_env; 8 | pub mod packet_inspector; 9 | // Tracking IBC state 10 | pub mod ibc_tracker; 11 | pub mod interchain_log; 12 | 13 | pub use error::InterchainDaemonError; 14 | 15 | /// Alias for an interchain Daemon Result 16 | pub type IcDaemonResult = Result; 17 | 18 | /// We want to export some major elements 19 | pub use channel_creator::{ChannelCreationValidator, ChannelCreator}; 20 | 21 | pub use interchain_env::DaemonInterchain; 22 | -------------------------------------------------------------------------------- /packages/interchain/interchain-mock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Adapter for interacting with ibc on cw-multi-test via cw-orch" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-interchain-mock" 7 | repository.workspace = true 8 | version = "0.9.0" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | cw-orch-core = { workspace = true } 14 | cw-orch-mock = { workspace = true } 15 | 16 | anyhow = { workspace = true } 17 | cosmrs = { workspace = true } 18 | cosmwasm-std = { workspace = true } 19 | cw-orch-interchain-core = { workspace = true } 20 | cw-utils = { workspace = true } 21 | ibc-relayer-types = { workspace = true } 22 | log = { workspace = true } 23 | serde = { workspace = true } 24 | serde_json = { workspace = true } 25 | thiserror = { workspace = true } 26 | 27 | [dev-dependencies] 28 | cw20 = { workspace = true } 29 | -------------------------------------------------------------------------------- /packages/interchain/interchain-mock/README.md: -------------------------------------------------------------------------------- 1 | # Cosmwasm Orchestrator Mock 2 | A Mock-chain implementation of [cw-orch-core](../cw-orch-core/README.md) used by integration tests of contracts 3 | This integrates mock ibc functionalities as well 4 | 5 | 6 | See [top-level README](../../README.md) -------------------------------------------------------------------------------- /packages/interchain/interchain-mock/src/error.rs: -------------------------------------------------------------------------------- 1 | use cosmwasm_std::StdError; 2 | use cw_orch_interchain_core::InterchainError; 3 | use thiserror::Error; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum InterchainMockError { 7 | #[error(transparent)] 8 | InterchainError(#[from] InterchainError), 9 | 10 | #[error(transparent)] 11 | Any(#[from] anyhow::Error), 12 | 13 | #[error(transparent)] 14 | StdError(#[from] StdError), 15 | 16 | #[error("Error validating IBC structures {0}")] 17 | ValidationError(#[from] ibc_relayer_types::core::ics24_host::error::ValidationError), 18 | 19 | #[error("Error validating IBC structures {0}")] 20 | ICSChannel(#[from] ibc_relayer_types::core::ics04_channel::error::Error), 21 | 22 | #[error("Configuration already registered for chain {0}")] 23 | AlreadyRegistered(String), 24 | 25 | #[error("mock for chain {0} not found")] 26 | MockNotFound(String), 27 | } 28 | 29 | impl From for InterchainError { 30 | fn from(value: InterchainMockError) -> Self { 31 | InterchainError::GenericError(value.to_string()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/interchain/interchain-mock/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Implementation of the interchain traits for the [cw_orch::prelude::Mock] environment 2 | 3 | mod error; 4 | mod interchain; 5 | 6 | use cosmwasm_std::testing::MockApi; 7 | use cw_orch_mock::cw_multi_test::MockApiBech32; 8 | pub use error::InterchainMockError; 9 | 10 | pub type MockInterchainEnv = interchain::MockInterchainEnvBase; 11 | pub type MockBech32InterchainEnv = interchain::MockInterchainEnvBase; 12 | -------------------------------------------------------------------------------- /packages/interchain/proto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "A helper crate for interaction with protos from different chains. Mostly used for handling cw20 coins and ibc transfers" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-proto" 7 | repository.workspace = true 8 | version = "0.9.0" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | cw-orch-core = { workspace = true } 14 | cw-orch-interchain-core = { workspace = true } 15 | cw-orch-traits = { workspace = true } 16 | 17 | anyhow = { workspace = true } 18 | 19 | cosmwasm-std = { workspace = true } 20 | ibc-proto = { workspace = true } 21 | ibc-relayer-types = { workspace = true } 22 | log = { workspace = true } 23 | osmosis-std = { version = "0.26.0" } 24 | prost = { workspace = true } 25 | prost-types = { workspace = true } 26 | tokio = { workspace = true } 27 | tonic = { workspace = true } 28 | 29 | [dev-dependencies] 30 | cw-orch-interchain-daemon = { workspace = true } 31 | cw-orch-starship = { workspace = true } 32 | env_logger = "0.11.5" 33 | speculoos = { workspace = true } 34 | -------------------------------------------------------------------------------- /packages/interchain/proto/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod tokenfactory; 2 | -------------------------------------------------------------------------------- /packages/interchain/starship/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors.workspace = true 3 | description = "Adapter for interacting with cosmoslogy:starship via cw-orch" 4 | edition.workspace = true 5 | license.workspace = true 6 | name = "cw-orch-starship" 7 | repository.workspace = true 8 | version = "0.7.0" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | reqwest = { version = "0.12.5", features = ["json"] } 14 | serde = { version = "1.0", features = ["derive"] } 15 | serde_json = "1.0.125" 16 | # Serde yaml deprecated 17 | cosmwasm-std = { workspace = true } 18 | ibc-chain-registry = { workspace = true } 19 | ibc-relayer-types = { workspace = true } 20 | thiserror = "1.0.63" 21 | yaml-rust2 = "0.8" 22 | 23 | cw-orch-core = { workspace = true } 24 | cw-orch-daemon = { workspace = true } 25 | tokio = { workspace = true } 26 | 27 | env_logger = "0.11" 28 | log.workspace = true 29 | url = "2.5.2" 30 | 31 | k8s-openapi = { version = "0.22.0", features = ["latest"] } 32 | kube = { version = "0.93.1", features = ["runtime", "derive", "ws"] } 33 | -------------------------------------------------------------------------------- /packages/interchain/starship/examples/starship.yaml: -------------------------------------------------------------------------------- 1 | chains: 2 | - id: stargaze-1 3 | name: stargaze 4 | numValidators: 1 5 | ports: 6 | rest: 1313 7 | rpc: 26653 8 | grpc: 30658 9 | faucet: 8000 10 | - id: juno-1 11 | name: juno 12 | numValidators: 1 13 | ports: 14 | rest: 1317 15 | rpc: 26657 16 | grpc: 30657 17 | faucet: 8001 18 | 19 | relayers: 20 | - name: osmo-juno 21 | type: hermes 22 | replicas: 1 23 | chains: 24 | - stargaze-1 25 | - juno-1 26 | config: 27 | event_source: 28 | mode: "pull" # default is "push" 29 | 30 | explorer: 31 | enabled: true 32 | ports: 33 | rest: 8080 34 | 35 | registry: 36 | enabled: true 37 | ports: 38 | rest: 8081 39 | -------------------------------------------------------------------------------- /packages/interchain/starship/src/client/error.rs: -------------------------------------------------------------------------------- 1 | #![allow(missing_docs)] 2 | use cw_orch_core::CwEnvError; 3 | use thiserror::Error; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum StarshipClientError { 7 | #[error(transparent)] 8 | Reqwest(#[from] reqwest::Error), 9 | 10 | #[error(transparent)] 11 | Url(#[from] url::ParseError), 12 | 13 | #[error("Error connecting to faucet at {0}")] 14 | FaucetError(String), 15 | 16 | #[error("Error connecting to registry at {0}")] 17 | RegistryError(String), 18 | 19 | #[error("Could not find hermes for these chains on localhost. Ensure it is running.")] 20 | HermesNotFound, 21 | 22 | #[error("daemon for chain {0} not found")] 23 | DaemonNotFound(String), 24 | 25 | #[error("chain config for chain {0} not found")] 26 | ChainConfigNotFound(String), 27 | 28 | #[error("There was a mismatch in the number of chains between the config object: {0} and the starship instance: {1}")] 29 | StarshipConfigMismatch(usize, usize), 30 | 31 | #[error("Configuration already registered for chain {0}")] 32 | AlreadyRegistered(String), 33 | 34 | #[error("Missing test mnemonic for chain {0}")] 35 | MissingTestMnemonic(String), 36 | 37 | #[error(transparent)] 38 | Kube(#[from] kube::Error), 39 | 40 | #[error(transparent)] 41 | StdIo(#[from] std::io::Error), 42 | 43 | #[error("Channel creation failed {0}-{1}, reason: {2}")] 44 | ChannelCreationFailure(String, String, String), 45 | } 46 | 47 | impl From for CwEnvError { 48 | fn from(val: StarshipClientError) -> Self { 49 | CwEnvError::AnyError(val.into()) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/interchain/starship/src/client/faucet.rs: -------------------------------------------------------------------------------- 1 | //! Rust implementation for interacting with a faucet similar to 2 | use cosmwasm_std::Addr; 3 | use serde::{Deserialize, Serialize}; 4 | 5 | use super::{error::StarshipClientError, registry::URL, StarshipClientResult}; 6 | 7 | /// Faucet structure that allows interacting with an online faucet 8 | #[derive(Debug, Clone)] 9 | pub struct Faucet(URL); 10 | 11 | /// Faucet request type 12 | #[derive(Serialize, Deserialize, Debug)] 13 | pub struct Request { 14 | /// Address of the address asking for funds 15 | pub address: String, 16 | /// Denom asked for 17 | pub denom: String, 18 | } 19 | 20 | impl Faucet { 21 | /// Get a faucet object from a url and port 22 | pub async fn new(url: impl ToString, port: impl ToString) -> Self { 23 | let path = format!("{}:{}", url.to_string(), port.to_string()); 24 | // Assert that the faucet is reachable 25 | let client = reqwest::Client::new(); 26 | client 27 | .get(format!("http://{path}/status")) 28 | .send() 29 | .await 30 | .map_err(|e| StarshipClientError::FaucetError(e.to_string())) 31 | .unwrap(); 32 | Self(path) 33 | } 34 | 35 | /// Requests funds for a given address 36 | /// Returns as soon as the funds are distributed to the address 37 | pub async fn request_funds( 38 | &self, 39 | address: &Addr, 40 | denom: impl Into, 41 | ) -> StarshipClientResult<()> { 42 | let faucet = &self.0; 43 | let url = format!("http://{}/{}", faucet, address); 44 | let client = reqwest::Client::new(); 45 | let response = client 46 | .post(&url) 47 | .json(&Request { 48 | address: address.to_string(), 49 | denom: denom.into(), 50 | }) 51 | .send() 52 | .await 53 | .map_err(|e| StarshipClientError::FaucetError(e.to_string()))?; 54 | if response.status().is_success() { 55 | Ok(()) 56 | } else { 57 | Err(StarshipClientError::FaucetError(response.text().await?)) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/interchain/starship/src/client/mod.rs: -------------------------------------------------------------------------------- 1 | //! Starship client allowing to interact 2 | //! This is rather low level. Most functions are exposed but rarely used outside of the starship struct in lib.rs 3 | 4 | mod core; 5 | mod error; 6 | pub mod faucet; 7 | pub mod registry; 8 | 9 | pub use crate::client::core::StarshipClient; 10 | pub use error::StarshipClientError; 11 | 12 | /// Custom Result that is used to simplify return types 13 | pub type StarshipClientResult = Result; 14 | -------------------------------------------------------------------------------- /packages/interchain/starship/starship/README.md: -------------------------------------------------------------------------------- 1 | # Starship Setup 2 | 3 | > See [starship docs](https://starship.cosmology.tech/) for detailed setup instructions. 4 | 5 | **Setup** 6 | 7 | Do this only once to create the Starship setup 8 | 9 | ```bash 10 | make setup 11 | ``` 12 | 13 | **Start Infrastructure** 14 | 15 | To start starship, use : 16 | ```bash 17 | make install 18 | ``` 19 | 20 | Once all nodes are up (see next section to check status) you are readi to use starship using cw-orchestrator. 21 | 22 | **Check status** 23 | 24 | To know the status of all the starship pods, use : 25 | 26 | ```bash 27 | kubectl get pods 28 | ``` 29 | 30 | Or for a watch version : 31 | ```bash 32 | make watch-pods 33 | ``` 34 | 35 | **Stop Infrastructure** 36 | 37 | 38 | ```bash 39 | make stop 40 | ``` 41 | 42 | Starship will crash when running for around a day. You will need to restart it from time to time to make sure everything is working. To do so, just stop the infrastructure, verify everything is stopped and `make install` it again 43 | 44 | **Delete Infrastructure** 45 | 46 | ```bash 47 | make clean-kind 48 | ``` 49 | -------------------------------------------------------------------------------- /packages/macros/cw-orch-contract-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | description = "Attribute macro for creating a contract interface." 4 | edition = { workspace = true } 5 | license = { workspace = true } 6 | name = "cw-orch-contract-derive" 7 | repository = { workspace = true } 8 | version = "0.21.1" 9 | 10 | [lib] 11 | proc-macro = true 12 | 13 | [dependencies] 14 | convert_case = "0.6.0" 15 | quote = "1" 16 | syn = { version = "2", features = ["full", "extra-traits"] } 17 | -------------------------------------------------------------------------------- /packages/macros/cw-orch-fns-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = { workspace = true } 3 | description = "Derive macro for generating contract interfaces." 4 | edition = { workspace = true } 5 | license = { workspace = true } 6 | name = "cw-orch-fns-derive" 7 | repository = { workspace = true } 8 | version = "0.23.1" 9 | 10 | [lib] 11 | proc-macro = true 12 | 13 | [dependencies] 14 | convert_case = "0.6.0" 15 | proc-macro2 = "1" 16 | quote = "1" 17 | syn = { version = "2", features = ["full", "extra-traits", "visit-mut"] } 18 | -------------------------------------------------------------------------------- /packages/macros/cw-orch-fns-derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit = "128"] 2 | 3 | mod fns_derive; 4 | mod helpers; 5 | mod query_fns; 6 | 7 | extern crate proc_macro; 8 | use helpers::{MsgType, SyncType}; 9 | use proc_macro::TokenStream; 10 | 11 | use syn::{parse_macro_input, ItemEnum}; 12 | 13 | /// Available attributes are : 14 | /// 15 | /// payable - The Execute function can accept funds 16 | /// fn_name - Modify the generated function name (useful for query or execute variants for instance) 17 | /// disable_fields_sorting - By default the fields are sorted on named variants. Disabled this behavior 18 | /// into - The field can be indicated in the generated function with a type that implements `Into` the field type 19 | #[proc_macro_derive(ExecuteFns, attributes(cw_orch))] 20 | pub fn cw_orch_execute(input: TokenStream) -> TokenStream { 21 | // We only parse and return the modified code if the flag is activated 22 | let ast = parse_macro_input!(input as ItemEnum); 23 | fns_derive::fns_derive(MsgType::Execute, SyncType::Sync, ast).into() 24 | } 25 | 26 | /// Available attributes are : 27 | /// 28 | /// returns - The return type of the query 29 | /// fn_name - Modify the generated function name (useful for query or execute variants for instance) 30 | /// disable_fields_sorting - By default the fields are sorted on named variants. Disabled this behavior 31 | /// into - The field can be indicated in the generated function with a type that implements `Into` the field type 32 | #[proc_macro_derive(QueryFns, attributes(cw_orch))] 33 | pub fn cw_orch_query(input: TokenStream) -> TokenStream { 34 | let ast = parse_macro_input!(input as ItemEnum); 35 | let sync_gen = fns_derive::fns_derive(MsgType::Query, SyncType::Sync, ast.clone()); 36 | let async_gen = fns_derive::fns_derive(MsgType::Query, SyncType::Async, ast); 37 | let tokens = quote::quote! { 38 | #sync_gen 39 | #async_gen 40 | }; 41 | tokens.into() 42 | } 43 | -------------------------------------------------------------------------------- /packages/macros/cw-orch-fns-derive/src/query_fns.rs: -------------------------------------------------------------------------------- 1 | use quote::quote; 2 | 3 | const RETURNS: &str = "returns"; 4 | 5 | /// Extract the query -> response mapping out of an enum variant. 6 | pub fn parse_query_type(v: &syn::Variant) -> proc_macro2::TokenStream { 7 | let response_ty: syn::Type = v 8 | .attrs 9 | .iter() 10 | .find(|a| a.path().is_ident(RETURNS)) 11 | .unwrap_or_else(|| panic!("missing return type for query: {}", v.ident)) 12 | .parse_args() 13 | .unwrap_or_else(|_| panic!("return for {} must be a type", v.ident)); 14 | quote!(#response_ty) 15 | } 16 | -------------------------------------------------------------------------------- /packages/macros/from-interface-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "Macro for generating From implementation for cw-orch interfaces of copied types" 3 | edition = "2021" 4 | license = "Apache-2.0" 5 | name = "cw-orch-from-interface-derive" 6 | version = "0.1.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [lib] 11 | proc-macro = true 12 | 13 | [dependencies] 14 | proc-macro2 = "1" 15 | quote = "1" 16 | syn = { version = "2", features = ["full", "extra-traits", "visit-mut"] } 17 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Before publishing, we need to download the cw-plus artifacts 4 | ./before_publish.sh 5 | 6 | # Before publishing, test the version with the Abstract implementation to make sure you're not breaking important API 7 | set -o errexit -o nounset -o pipefail 8 | command -v shellcheck >/dev/null && shellcheck "$0" 9 | 10 | function print_usage() { 11 | echo "Usage: $0 [-h|--help]" 12 | echo "Publishes crates to crates.io." 13 | } 14 | 15 | if [ $# = 1 ] && { [ "$1" = "-h" ] || [ "$1" = "--help" ] ; } 16 | then 17 | print_usage 18 | exit 1 19 | fi 20 | 21 | # these are imported by other packages 22 | BASE_PACKAGES=" 23 | cw-orch-contract-derive 24 | cw-orch-fns-derive 25 | cw-orch-core 26 | cw-orch-traits 27 | cw-orch-mock 28 | cw-orch-networks 29 | " 30 | 31 | INTERCHAIN_PACKAGES=" 32 | interchain-core 33 | starship 34 | interchain-daemon 35 | interchain-mock 36 | proto 37 | " 38 | 39 | CORE="cw-orch-daemon cw-orch cw-orch-interchain" 40 | 41 | INTEGRATIONS=" 42 | cw-plus 43 | " 44 | 45 | for pack in $BASE_PACKAGES; do 46 | ( 47 | cd "packages/$pack" 48 | echo "Publishing $pack" 49 | cargo publish 50 | ) 51 | done 52 | 53 | for lib in $INTERCHAIN; do 54 | ( 55 | cd "packages/interchain/$lib" 56 | echo "Publishing $lib" 57 | cargo publish 58 | ) 59 | done 60 | 61 | for lib in $CORE; do 62 | ( 63 | cd "$lib" 64 | echo "Publishing $lib" 65 | cargo publish 66 | ) 67 | done 68 | 69 | for integration in $INTEGRATIONS; do 70 | ( 71 | cd "packages/integrations/$integration" 72 | echo "Publishing $integration" 73 | cargo publish 74 | ) 75 | done 76 | 77 | echo "Everything is published!" 78 | 79 | # 80 | # VERSION=$(< Cargo.toml grep -m 1 version | sed 's/-/_/g' | grep -o '".*"' | sed 's/"//g'); 81 | # git push 82 | # git tag v"$VERSION" 83 | # git push origin v"$VERSION" -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # stable 2 | hard_tabs = false 3 | newline_style = "unix" 4 | tab_spaces = 4 5 | 6 | # unstable_features = true 7 | # imports_granularity = "Crate" 8 | 9 | # unstable... should we require `rustup run nightly cargo fmt` ? 10 | # or just update the style guide when they are stable? 11 | #fn_single_line = true 12 | #format_code_in_doc_comments = true 13 | #overflow_delimited_expr = true 14 | #reorder_impl_items = true 15 | #struct_field_align_threshold = 20 16 | #struct_lit_single_line = true 17 | #report_todo = "Always" 18 | -------------------------------------------------------------------------------- /taplo.toml: -------------------------------------------------------------------------------- 1 | [formatting] 2 | align_entries = true 3 | column_width = 100 4 | inline_table_expand = false 5 | reorder_keys = true 6 | -------------------------------------------------------------------------------- /test_contracts/compatibility-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "Mock constract for cw-orch macro testing" 3 | edition = { workspace = true } 4 | keywords = ["cosmwasm", "blockchain"] 5 | name = "cw-orch-compatibility-test" 6 | version = "0.1.0" 7 | 8 | exclude = [".env"] 9 | 10 | [lib] 11 | crate-type = ["cdylib", "rlib"] 12 | 13 | [features] 14 | default = ["export"] 15 | export = [] 16 | interface = [] 17 | 18 | [dependencies] 19 | cosmwasm-schema = "2.0" 20 | cosmwasm-std = { workspace = true } 21 | schemars = "0.8.10" 22 | serde = { workspace = true } 23 | serde_json = "1.0.79" 24 | thiserror = { version = "1.0.21" } 25 | # This version should not be a path dependency and be kept to the last cw-orch version (beyond v0.23) 26 | # Keeping a different package until v0.23 to avoid package conflicts 27 | cw-orch = { package = "aaa-test-cw-orch", version = "0.25" } 28 | # Keep the old-cw-orch version to 0.22 for backwards compatibility 29 | old-cw-orch = { package = "cw-orch", version = "0.24" } 30 | -------------------------------------------------------------------------------- /test_contracts/compatibility-test/README.md: -------------------------------------------------------------------------------- 1 | This folder is used for testing backwards compatibility of cw-orch macros with the older macro versions. 2 | The cw-orch version needs to stay at 0.22 for this test because it's the first stable version of cw-orch-core. 3 | -------------------------------------------------------------------------------- /wasm_contracts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $(arch) == "arm64" ]]; then 4 | image="cosmwasm/optimizer-arm64:0.16.0" 5 | else 6 | image="cosmwasm/optimizer:0.16.0" 7 | fi 8 | 9 | # Optimized builds 10 | docker run --rm -v "$(pwd)":/code \ 11 | --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/contracts-ws/target \ 12 | --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ 13 | ${image} ./contracts-ws 14 | --------------------------------------------------------------------------------