{"id":13471014,"url":"https://github.com/Cardinal-Cryptography/ink-wrapper","last_synced_at":"2025-03-26T13:30:42.243Z","repository":{"id":136296853,"uuid":"610809995","full_name":"Cardinal-Cryptography/ink-wrapper","owner":"Cardinal-Cryptography","description":"Generator for typed wrappers for calling substrate smart contracts","archived":false,"fork":false,"pushed_at":"2024-03-11T15:27:22.000Z","size":749,"stargazers_count":11,"open_issues_count":10,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-30T02:58:02.689Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cardinal-Cryptography.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-07T14:26:46.000Z","updated_at":"2024-09-03T21:47:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"d87b4bf2-943c-4c21-8a25-dc912b5ab771","html_url":"https://github.com/Cardinal-Cryptography/ink-wrapper","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fink-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fink-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fink-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cardinal-Cryptography%2Fink-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cardinal-Cryptography","download_url":"https://codeload.github.com/Cardinal-Cryptography/ink-wrapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245662710,"owners_count":20652068,"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":"2024-07-31T16:00:38.459Z","updated_at":"2025-03-26T13:30:41.627Z","avatar_url":"https://github.com/Cardinal-Cryptography.png","language":"Rust","funding_links":[],"categories":["🛠️ Libraries \u0026 Standards"],"sub_categories":["Testnets"],"readme":"# ink-wrapper\n\n![ink-wrapper](https://img.shields.io/crates/v/ink-wrapper.svg)\n\n`ink-wrapper` is a tool that generates type-safe code for calling a substrate smart contract based on the metadata\n(`.json`) file for that contract.\n\n## Installation\n\nInstall the tool from [crates.io](https://crates.io):\n\n```bash\ncargo +nightly-2023-04-19 install ink-wrapper --locked --force\n```\n\nNote that this uses `nightly-2023-04-19`. You will need to install the toolchain first. You may try with just `+nightly` to use whatever nightly you already have installed, but this particular version should work. The crate will most likely compile on another toolchain, but generate broken code afterwards, see https://github.com/udoprog/genco/issues/39.\n\n## Usage\n\n### Note on compatibility.\n\nThe last release compatible with `aleph_client` is version [`0.6.0`](https://crates.io/crates/ink-wrapper-types/0.6.0). Note though that it's compatible with `aleph-client` in version `3.0.0` as this is the last version available in [crates.io](https://crates.io/crates/aleph_client/versions). We do not guarantee it will work with Testnet or Mainnet since their runtimes may differ in ways that are not compatible with `aleph_client 3.0.0`.\n\nCurrent release focuses on compatibility with [drink](https://crates.io/crates/drink).\n\nFuture releases will try to address the support for live chains.\n\n### Setup\n\nGiven some metadata file like `my_contract.json` run the tool and save the output to a file in your project:\n\n```bash\nink-wrapper -m my_contract.json \u003e src/my_contract.rs\n```\n\nWe only take minimal steps to format the output of the tool, so we recommend that you run it through a formatter when\n(re)generating:\n\n```bash\nink-wrapper -m my_contract.json | rustfmt --edition 2021 \u003e src/my_contract.rs\n```\n\nThe output should compile with no warnings, please create an issue if any warnings pop up in your project in the\ngenerated code.\n\nMake sure the file you generated is included in your module structure:\n\n```rust\nmod my_contract;\n```\n#### DRink!\n\nAdd the following to your `Cargo.toml:\n```toml\n[dependencies]\ndrink = \"0.8.6\"\nink_primitives = \"4.3.0\"\nink-wrapper-types = { version = \"0.7.0\", default-feauters = false, features = [ \"drink\" ] }\nscale = { package = \"parity-scale-codec\", version = \"3\", default-features = false, features = [ \"derive\" ] }\n```\n\nAfter generating the wrappers, the `my_contract` will contain `Instance` struct which represents the contract's state.\n\nThe easiest way to write a test is to use drink's unit test macro which will set up the `drink::session::Sessin\u003cMinimalRuntime\u003e` object:\n```rust\n// Auto-generated wrappers need to be added to the crate.\nmod my_contract;\n\n// Minimal imports\nuse ink_wrapper_types::{Connection, ToAccountId};\nuse drink::{session::Session, AccountId32};\n\n#[drink::test]\nfn my_test(mut session: Session) {\n    // Upload code to DRink! backend\n    let _code_hash = session.upload_code(my_contract::upload()).expect(\"Upload to succeed\");\n\n    // Instantiate the contract.\n    let address = session.instantiate(my_contract::Instance::new(1000))\n        .expect(\"No pallet-contract errors\")\n        .result // AccountId, address, of the new instance\n        .to_account_id() // Map to ink_primitives type\n        .into();\n\n    // Now we can call contract's methods. They're provided by the trait `my_contract::MyContract` (depends on your actual contract name)\n    use my_contract::MyContract as _;\n\n    // Construct the call object.\n    let exec_call = address.some_exec_call();\n    \n    // Execute it.\n    let res = session.execute(exec_call);\n}\n```\n\nFor more comprehensive examples on actual contract wrappers, see `tests` directory.\n\n#### `aleph_client` (deprecated from `0.7.0`)\n\nYou will need the following dependencies for the wrapper to work:\n\n```toml\nink-wrapper-types = \"0.6.0\"\nscale = { package = \"parity-scale-codec\", version = \"3\", default-features = false, features = [\"derive\"] }\nink_primitives = \"4.2.1\"\n\n# You only need this one if you have messages of the form `Trait::message`, like the ones generated by openbrush, for\n# example.\nasync-trait = \"0.1.68\"\n\n# This one is optional, but you most likely need it as well if you're using the default `aleph_client` implementation\n# for actually making calls. Otherwise, you will need to implement `ink_wrapper_types::Connection` and\n# `ink_wrapper_types::SignedConnection` yourself.\naleph_client = \"3.0.0\"\n```\n\n##### Basic usage\n\nWith that, you're ready to use the wrappers in your code. The generated module will have an `Instance` struct that\nrepresents an instance of your contract. You can either talk to an existing instance by converting an `account_id` to\nan `Instance`:\n\n```rust\nlet account_id: ink_primitives::AccountId = ...;\nlet instance: my_contract::Instance = account_id.into();\n```\n\nOr (assuming the contract code has already been uploaded) create an instance using one of the generated constructors:\n\n```rust\nlet instance = conn.instantiate(my_contract::Instance::some_constructor(arg1, arg2)).await?;\n```\n\nAnd then call methods on your contract:\n\n```rust\nlet result = conn.read(instance.some_getter(arg1, arg2)).await?;\nlet tx_info = conn.exec(instance.some_mutator(arg1, arg2)).await?;\n```\n\nNote that any methods that have names like `Trait::method_name` will be grouped into traits in the generated module. You\nmight encounter this if you're using openbrush, for example their `PSP22` implementation generates method names like\n`PSP22::balance_of`. You need to `use` the generated traits to access these:\n\n```rust\nuse my_contract::PSP22 as _;\nconn.read(instance.balance_of(account_id)).await?\n```\n\nIn the examples above, `conn` is anything that implements `ink_wrapper_types::Connection` (and\n`ink_wrapper_types::SignedConnection` if you want to use constructors or mutators). Default implementations are provided\nfor the connection in `aleph_client`.\n\n##### Events\n\n`ink_wrapper_types::Connection` also allows you to fetch events for a given `TxInfo`:\n\n```rust\nuse ink_wrapper_types::Connection as _;\n\nlet tx_info = conn.exec(instance.some_mutator(arg1, arg2)).await?;\nlet all_events = conn.get_contract_events(tx_info).await?;\nlet contract_events = all_events.for_contract(instance);\nlet sub_contract_events = all_events.for_contract(sub_contract);\n```\n\nThe `all_events` object above may contain events from multiple contracts if the contract called into them. In that case,\nyou can filter and parse these events by calling `for_contract` on it, with the various contracts you're interested in.\n\n##### Code upload\n\nIf you provide a compile-time path to the compiled `WASM`:\n\n```bash\nink-wrapper -m my_contract.json --wasm-path ../contracts/target/ink/my_contract.wasm\n```\n\nyou will also be able to use the generated wrapper to upload the contract:\n\n```rust\nconn.upload(my_contract::upload()).await\n```\n\nNote, that the `upload` function will return `Ok(TxInfo)` so long as the transaction was submitted successfully and the\ncode hash of the metadata matches the uploaded code. If the code already existed on the chain, no error is returned. You\ncan verify this condition yourself by looking at the events at the returned `TxInfo` and checking if they contain a\n`CodeStored` event.\n\n### Example\n\nLook at `tests` in the project's repo for a fuller example. Note that `tests/drink` is missing the actual\nwrappers, which are normally generated when testing. The easiest way to regenerate them is by running\n`make all-dockerized` (requires docker) - see [Development](#development) for more on that.\n\n## Development\n\nUse the commands provided in the `Makefile` to replicate the build process run on CI:\n\n```bash\nmake help\n```\n\nThe most hassle-free is to just run everything in docker:\n\n```bash\nmake all-dockerized\n```\n\nIf you have the tooling installed on your host and start a node yourself, you can also run the build on your host:\n\n```bash\nmake all\n```\n\nIn case there are any runaway containers from `all-dockerized` you can kill them:\n\n```bash\nmake kill\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCardinal-Cryptography%2Fink-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCardinal-Cryptography%2Fink-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCardinal-Cryptography%2Fink-wrapper/lists"}