{"id":26905848,"url":"https://github.com/abstractsdk/cw-orch-counter-example","last_synced_at":"2025-04-01T10:59:08.367Z","repository":{"id":199872903,"uuid":"703637272","full_name":"AbstractSDK/cw-orch-counter-example","owner":"AbstractSDK","description":"Describes an example for integrating cw-orch in a contract","archived":false,"fork":false,"pushed_at":"2024-03-27T15:47:54.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-03-27T16:59:26.037Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AbstractSDK.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-10-11T16:01:44.000Z","updated_at":"2023-10-12T08:47:29.000Z","dependencies_parsed_at":"2023-10-13T03:50:21.217Z","dependency_job_id":null,"html_url":"https://github.com/AbstractSDK/cw-orch-counter-example","commit_stats":null,"previous_names":["abstractsdk/cw-orch-counter-example"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbstractSDK%2Fcw-orch-counter-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbstractSDK%2Fcw-orch-counter-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbstractSDK%2Fcw-orch-counter-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbstractSDK%2Fcw-orch-counter-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AbstractSDK","download_url":"https://codeload.github.com/AbstractSDK/cw-orch-counter-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246628226,"owners_count":20808106,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-01T10:59:07.793Z","updated_at":"2025-04-01T10:59:08.347Z","avatar_url":"https://github.com/AbstractSDK.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Counter Contract\n\nThis guide features the counter contract as a prime example to demonstrate the capabilities of cw-orchestrator. Often serving as the introductory example for new CosmWasm developers, the counter contract is an ideal candidate for showcasing the functionalities of cw-orchestrator.\n\nFor a high-level overview tutorial that explains how to adapt a contract for compatibility with cw-orchestrator, please refer to [our documentation.](https://orchestrator.abstract.money/single_contract/interfaces.html) This README aims to provide a more detailed set of instructions, serving as an extended summary of that tutorial.\n\n## Struct Creation and Endpoint Registration\n\n### Contract Macros\n\nThe most straightforward way to integrate cw-orchestrator into your contracts is by using the `interface_entry_point` macro. Applying this macro to each of your contract's entry-points will generate a struct that is compatible with cw-orchestrator, while also registering the necessary variables.\n\nTake a look at the [contract.rs](./src/contract.rs) file, it's that easy!\nThe supported endpoints are:\n\n- Instantiate\n- Query\n- Execute\n- Migrate\n- Reply\n- Sudo\n\nYou can see in the [contract.rs](./src/contract.rs) file that we feature flag that macro in order to not include cw-orch into the contract's build artifact. You have to realize that including this macro with a feature flag **won't change anything** to the actual wasm file that you are uploading on-chain if you don't enable this feature by default.\nA good practice is to put this macro declaration right after the `cosmwasm_std::entry_point` macro definition.\n\n\u003e **_NOTE_** In order to be compatible with this method of integration, there are a few prerequisites. If your contract doesn't match **one** of those criteria, you should opt for the [manual way](#manual-integration) approach. It's not much more effort, you can do it! Here are the pre-requisites:\n\u003e - All the entry-points must be defined in the same file. This is required because of the way traits are implemented for the generated struct.\n\u003e - Your artifacts (*.wasm files) should be contained in the artifacts folder of the crate OR the workspace. i.e. there should be a folder named `artifacts` in the root of your crate or workspace.\n\u003e  \u003e   If you define your contract with this method, cw-orchestrator will look for artifacts files that match your crate name (with `-` converted to `_`) in an `artifacts` folder. It starts looking in the root of the current crate and goes up until it finds a directory named `artifacts` or fails.\n\u003e  \u003e  For instance, here, the artifacts are located at the [workspace root](../../artifacts/). The file named [counter_contract.wasm](../../artifacts/counter_contract.wasm) will be used by this struct to upload the contract on-chain. \n\n**Integrating via this method will create a struct which is named after the current crate's name converted to PascalCase.** This structure has a `new` constructor that you can use [following the steps in our documentation](https://orchestrator.abstract.money/single_contract/interfaces.html#constructor).\n\nFor example in the `counter` contract, it will define an `CounterContract` struct inside the `contract.rs` file because the package name is `counter-contract`, defined [here](../counter/Cargo.toml).\n\n### Manual Integration\n\nIf for any reason you don't want to use the beautiful automatic version we described above, you can still do things manually, we have [a nice tutorial here](https://orchestrator.abstract.money/single_contract/interfaces.html#customizable-interface-macro). This will allow you to customize the entry-points of your contract as well as the location of the artifacts directory for your wasm files.\n\n## Endpoint Function Generation\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth\u003e Tired of having to use endless schemas?\u003c/th\u003e\n\u003cth\u003e Tired of having to redeclare your field names every time you want to declare an struct?\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr style=\"vertical-align: top;\"\u003e\n\u003ctd\u003e\n\n```json\n    {\n        \"swap\": {\n            \"offer_asset\": {\n                \"native\":{\n                    \"denom\":\"ujuno\"\n                }\n            },\n            \"ask_asset\": {\n                \"native\":{\n                    \"denom\":\"uluna\"\n                }\n            },\n            \"amount\": \"3465\"\n        }\n    }\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```rust,ignore\n    dex::core::swap::ExecuteMsg::Swap{\n        offer_asset: CwAsset::Native(\"ujuno\"),\n        ask_asset: CwAsset::Native(\"uluna\"),\n        amount: 3465u128.into()\n    }\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\nWith orchestrator, you know your types **and** you get to use the Rust syntax you are used to! Your code can now look like this:\n```rust,ignore\n    dex.swap(CwAsset::Native(\"ujuno\"), CwAsset::Native(\"uluna\"), 3465u128.into())\n```\n\nIn order to be able to interact in this manner with your code, you just need to add : \n- `#[derive(cw_orch::ExecuteFns)]` above of your `ExecuteMsg` definitions [You can see an example here](./src/msg.rs)\n- `#[derive(cw_orch::QueryFns)]` above of your `QueryMsg` definitions [You can see an example here](./src/msg.rs)\n\nAnd you are all set!\n\n### Details\n\nActually, the query macro does need additional definitions. If you haven't already, you need to define the `cosmwasm_schema::QueryResponses` macro. This is used by cw-orchestrator to determine the return type of your queries. This is absolutely marvelous and your code can be transformed:\n\n```rust,ignore\n    // Previous\n    let balance: BalanceResponse = cosmwasm_smart_query(\"my_cw20_address\", cw20::QueryMsg::Balance{\n        address: \"my_address\".to_string(),\n    })?;\n\n    // Now\n    let balance = my_cw20.balances(\"my_address\".to_string())?;\n```\n\nBetter right ?\n\n### Additional attributes\n\n#### `payable`\n\nLet's see an example for executing a message (from a money market for instance).\n\n```rust,ignore\n    money_market.deposit_stable()?;\n```\n\nThere's a problem with the above function. The money market only knows how much you deposit into it by looking at the funds you send along with the transaction. Cw-orchestrator doesn't ask for funds by default. However, to allow attaching funds to a transaction, you can add the `#[payable]` attribute on your enum variant like so:\n\n```rust, ignore\n    #[derive(ExecuteFns)]\n    enum ExecuteMsg{\n        UpdateConfig{\n            config_field: String\n        },\n        #[payable]\n        DepositStable{}\n        ...\n    }\n```\n\nBe defining this attribute, you can now use:\n```rust,ignore\n    money_market.deposit_stable(coins(456, \"ujunox\"))?;\n```\n\n#### `fn_name`\n\nBe careful what you name your enum variants, you could stumble upon one of the reserved keywords of cw-orch. If this happens, you can use the fn_name attribute to rename a generated function.\n\n```rust,ignore\n\n    ExecuteMsg{\n        #[fn_name(\"proxy_execute\")]\n        Execute{\n            msg: CosmoMsg\n        }\n    }\n\n    // Will error because the execute function is reserved for contract execution. Will not even compile actually\n    money_market.execute(message_to_execute_via_a_proxy)?;\n```\n\n```rust,ignore\n    ExecuteMsg{\n        #[fn_name(\"proxy_execute\")]\n        Execute{\n            msg: CosmoMsg\n        }\n    }\n    // This works smoothly !\n    money_market.proxy_execute(message_to_execute_via_a_proxy)?;\n```\n\nThis is also true for query functions.\n\n\n#### `impl_into`\n\nFor more details about this attribute, [see the full documentation](https://orchestrator.abstract.money/single_contract/interfaces.html#impl_into-attribute)\n\n## Other cw-orch traits\n\n### Deploy\n\ncw-orchestrator defines the [Deploy](../../cw-orch/src/deploy.rs) trait that allows developers to create an interface that allows themselves or other developers to:\n\n1. Easily deploy their codebase on a test chain or elsewhere. [See it live here](https://github.com/AbstractSDK/abstract/blob/main/framework/scripts/src/bin/full_deploy.rs#L29).\n2. Provide bindings (addresses, code_ids), for other developers to integrate with the platform. [See it live here](https://github.com/AbstractSDK/abstract/blob/main/modules/contracts/apps/croncat/examples/deploy.rs#L32).\n\nThis is more powerful than simply exposing the single contract interfaces, because it allows full customization of the deployment procedure. It also allows shipping other custom methods for simplifying the life of the integrator.\n\nImagine you are a developer that wants to integrate with [Abstract](https://github.com/AbstractSDK/). With this deploy trait, you could test your application like so:\n\n```rust,ignore\nuse abstract_interface::Abstract;\nuse cw_orch::daemon::networks::JUNO_1;\n\npub fn test() -\u003e anyhow::Result\u003c()\u003e{\n    let chain = Daemon::builder()\n        .chain(JUNO_1) \n        .handle(Runtime::new().unwrap().handle()) \n        .build()?;\n        \n    // Here you load all the contracts from the addresses and code_ids that abstract ships along with the Deploy trait they implement\n    let abstract_deploy = Abstract::load_from(chain.clone())?;\n    \n    // Then you can call abstract specific commands without having to specify any addresses yourself. \n    // You just need to import the crate and you can interact with it directly\n    let new_account = abstract_deploy.account_factory.create_new_account(\n        AccountDetails{\n            name: \"New account name, input something funny ?\".to_string(),\n            description: Some(\"Account description\".to_string()),\n            link: None,\n            namespace: None,\n            base_asset: None,\n            install_modules: vec![],\n        },\n        GovernanceDetails::Monarchy{\n            monarch: \"\u003cmonarch-address\u003e\"\n        }\n    )?;\n\n    println!(\"Created new abstract account with manager address : {}\", new_account.manager.address()?);\n    Ok(())\n}\n```\n\nIn our example, all the abstract core addresses, which we require to interact with the contracts, are included in the `abstract_interface` crate directly. By using this Deploy trait, Abstract includes the addresses of their deployment and code ids in their published software, they allows other developers to easily interact and integrate with their platform.\n\nTo do this for your project you need to verify certain conditions.\n\n#### Conditions for shipping addresses in a crate that implements the Deploy trait\n\nInside the deploy trait functions, you can define multiple methods. The two principle methods are:\n\n- `Deploy::store_on` : for storing all contracts in the bundle on chains (Upload)\n- `Deploy::deploy_on` : One stop function for deploying your bundle on a chain. This usually calls the `store_on` method before instantiating all contracts sequentially\n\nAfter those functions are implemented you can link up the deployment data with your objects. For users to be able to retrieve addresses, they need to come from somewhere. In order for bundle maintainers to allow that, they should implement the `Deploy::load_from`, just like we do at abstract:\n\n```rust,ignore\n    fn deployed_state_file_path(\u0026self) -\u003e Option\u003cString\u003e {\n        let crate_path = env!(\"CARGO_MANIFEST_DIR\");\n\n        Some(\n            PathBuf::from(crate_path)\n                // State file of your deployment\n                .join(\"state.json\")\n                .display()\n                .to_string(),\n        )\n    }\n\n    fn load_from(chain: Chain) -\u003e Result\u003cSelf, Self::Error\u003e {\n        let mut abstr = Self::new(chain);\n        // We set all the contract's default state (addresses, code_ids)\n        abstr.set_contracts_state();\n        Ok(abstr)\n    }\n```\n\nThe `Deploy::set_contracts_state` doesn't need to be re-implemented and it allows to override the daemon state file and use the deployed addresses and code_ids instead. Doing this decouples the local state of the users from the deployed state of the maintainers/project. \n\nYou can customize the `Deploy::deployed_state_file_path` and `Deploy::load_from` methods, be we recommend doing something similar to simplify exporting the state correctly. \n\n\n\u003e **_NOTE_** You should check out the [Abstract bundle implementation](https://github.com/AbstractSDK/abstract/blob/main/framework/packages/abstract-interface/src/deployment.rs) to understand how to ship a bundle. In abstract, we have a file named `state.json` in the crate root with all the abstract state. We refer to it by referring to the absolute crate path and adding `\"state.json\"` to it. \n\u003e \n\u003e We recommend defining this location from the absolute crate path `env!(\"CARGO_MANIFEST_DIR\")` for it to be accessible even when imported from a crate. \n\nOur abstract workspace structure looks like this : \n\n```\n.\n├── artifacts\n├── contracts\n│   ├── contract1\n│   │   └── src\n│   │       ├── contract.rs\n│   │       └── ...\n│   └── contract2\n│       └── src\n│           ├── contract.rs\n│           └── ...\n├── packages\n|   └── interface \n|       ├── src\n│       │   ├── deploy.rs   // \u003c-- Definition of the deploy struct and implementation of the Deploy trait. \n|       │   |               // \u003c--   Leverages contract1 and contract2 structures\n│       │   └── ...\n│       └── state.json      /// \u003c-- Usually a symlink to the state.json file you use for deployment (by default in ~/.cw-orchestrator)\n├── scripts\n|   └── src\n|       └── bin             // \u003c-- Your deployment script can be located here\n└── .env \t\t\t\t\t// \u003c-- Place your .env file at the root of your workspace\n```\n\nIn the Deploy trait implementation (here in`deploy.rs` file), use this to indicate that `packages/interface/state.json` has your state : \n```rust\n    fn deployed_state_file_path(\u0026self) -\u003e Option\u003cString\u003e {\n        let crate_path = env!(\"CARGO_MANIFEST_DIR\");\n\n        Some(\n            PathBuf::from(crate_path)\n                .join(\"state.json\")\n                .display()\n                .to_string(),\n        )\n    }\n```\n\nMake sure you are adding the `set_contract_state`, helper function in the `load_from` function of the `Deploy` trait to make sure your deployment leverages the saved contract addresses. \n\n```rust\n\n    fn load_from(chain: Chain) -\u003e Result\u003cSelf, Self::Error\u003e {\n        let mut abstr = Self::new(chain);\n        // We register all the contracts default state\n        abstr.set_contracts_state();\n        Ok(abstr)\n    }\n```\n\n\nThose 2 steps will allow users to access your state from their script when importing you `interface` crate.\n\n#### Limitations\n\n\n## Learn More\nDon't hesitate to check out the [examples](./examples) and [tests](./tests) of this crate to learn more and get inspiration from code directly","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabstractsdk%2Fcw-orch-counter-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabstractsdk%2Fcw-orch-counter-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabstractsdk%2Fcw-orch-counter-example/lists"}