TS Codegen
Introduction

@cosmwasm/ts-codegen

Generate TypeScript SDKs for your CosmWasm smart contracts

npm install -g @cosmwasm/ts-codegen

The quickest and easiest way to interact with CosmWasm Contracts. @cosmwasm/ts-codegen converts your CosmWasm smart contracts into dev-friendly TypeScript classes so you can focus on shipping code.

🎥 Checkout our video playlist (opens in a new tab) to learn how to use ts-codegen!

Table of contents

Quickstart

Clone your project and cd into your contracts folder

git clone https://github.com/public-awesome/launchpad.git
cd launchpad/contracts/sg721-base/

Run cosmwasm-ts-codegen to generate your code.

cosmwasm-ts-codegen generate \
          --plugin client \
          --schema ./schema \
          --out ./ts \
          --name SG721 \
          --no-bundle

The output will be in the folder specified by --out, enjoy!

Usage

You can get started quickly using our cli by globally installing via npm:

npm install -g @cosmwasm/ts-codegen

Programmatic Usage

For production usage, we recommend setting up a build script that uses the main entry point:

import codegen from "@cosmwasm/ts-codegen";
 
codegen({
  contracts: [
    {
      name: "SG721",
      dir: "./path/to/sg721/schema",
    },
    {
      name: "Minter",
      dir: "./path/to/Minter/schema",
    },
  ],
  outPath: "./path/to/code/src/",
 
  // options are completely optional ;)
  options: {
    bundle: {
      bundleFile: "index.ts",
      scope: "contracts",
    },
    types: {
      enabled: true,
    },
    client: {
      enabled: true,
    },
    reactQuery: {
      enabled: true,
      optionalClient: true,
      version: "v4",
      mutations: true,
      queryKeys: true,
      queryFactory: true,
    },
    recoil: {
      enabled: false,
    },
    messageComposer: {
      enabled: false,
    },
    messageBuilder: {
      enabled: false,
    },
    useContractsHooks: {
      enabled: false,
    },
  },
}).then(() => {
  console.log("✨ all done!");
});

Types

Typescript types and interfaces are generated in separate files so they can be imported into various generated plugins.

see example output code (opens in a new tab)

Types Options

optiondescription
types.enabledenable type generation
types.aliasExecuteMsggenerate a type alias based on the contract name
types.aliasEntryPointsgenerate type aliases for the entry points based on the contract name

Client

The client plugin will generate TS client classes for your contracts. This option generates a QueryClient for queries as well as a Client for queries and mutations.

see example output code (opens in a new tab)

Client Options

optiondescription
client.enabledgenerate TS client classes for your contracts
client.execExtendsQueryexecute should extend query message clients
client.noImplicitOverrideshould match your tsconfig noImplicitOverride option

Client via CLI

cosmwasm-ts-codegen generate \
    --plugin client
    --schema ./schema \
    --out ./ts \
    --name MyContractName

React Query

Generate react-query v3 (opens in a new tab) or react-query v4 (opens in a new tab) bindings for your contracts with the react-query command.

see example output code (opens in a new tab)

React Query Options

optiondescription
reactQuery.enabledenable the react-query plugin
reactQuery.optionalClientallows contract client to be undefined as the component renders
reactQuery.queryKeysgenerates a const queryKeys object for use with invalidations and set values
reactQuery.queryFactorygenerates a const queryFactory object for useQueries and prefetchQueries use
reactQuery.versionv4 uses @tanstack/react-query and v3 uses react-query
reactQuery.mutationsalso generate mutations
reactQuery.camelizeuse camelCase style for property names

React Query via CLI

Here is an example without optional client, using v3 for react-query, without mutations:

cosmwasm-ts-codegen generate \
    --plugin client \
    --plugin react-query \
    --schema ./schema \
    --out ./ts \
    --name MyContractName \
    --version v3 \
    --no-optionalClient \
    --no-mutations

Example with optional client, using v4, with mutations:

cosmwasm-ts-codegen generate \
    --plugin react-query \
    --schema ./schema \
    --out ./ts \
    --name MyContractName \
    --optionalClient \
    --version v4 \
    --mutations

Recoil

Generate recoil (opens in a new tab) bindings for your contracts with the recoil command.

see example output code (opens in a new tab)

Recoil via CLI

cosmwasm-ts-codegen generate \
    --plugin recoil \
    --schema ./schema \
    --out ./ts \
    --name MyContractName

Recoil Options

optiondescription
recoil.enabledenable the recoil plugin

Message Composer

Generate pure message objects with the proper utf8 encoding and typeUrl configured that you can broadcast yourself via cosmjs with the message-composer command.

see example output code (opens in a new tab)

Message Composer via CLI

cosmwasm-ts-codegen generate \
    --plugin message-composer \
    --schema ./schema \
    --out ./ts \
    --name MyContractName

Message Composer Options

optiondescription
messageComposer.enabledenable the messageComposer plugin

Message Builder

Generate raw message jsons for use in your application with the message-builder command.

see example output code (opens in a new tab)

Message Builder via CLI

cosmwasm-ts-codegen generate \
    --plugin message-builder \
    --schema ./schema \
    --out ./ts \
    --name MyContractName

Message Builder Options

optiondescription
messageBuilder.enabledenable the messageBuilder plugin

Use Contracts Hooks

optiondescription
useContractsHooks.enabledenable the useContracts plugin

Use Contracts Provider Usage

import { useChain } from "@cosmos-kit/react";
import { ContractsProvider } from "../path/to/codegen/contracts-context";
 
export default function YourComponent() {
  const { address, getCosmWasmClient, getSigningCosmWasmClient } =
    useChain(chainName);
 
  return (
    <ContractsProvider
      contractsConfig={{
        address,
        getCosmWasmClient,
        getSigningCosmWasmClient,
      }}
    >
      <SomeCoolComponent />
    </ContractsProvider>
  );
}

Use Contracts Provider Babel/TSC config

If you're using Babel, please make sure include '@babel/preset-react' in devDeps and presets in .babelrc.js:

presets: ["@babel/typescript", "@babel/env", "@babel/preset-react"];

For tsc, you should set the jsx option to 'react' in your tsconfig.json.

Use Contracts Hooks Usage

Once enabled, you can get contracts very simply:

const { marketplace } = useContracts();
const marketplaceClient = marketplace.signingClient(marketplaceContract);
await marketplaceClient.updateAskPrice({
  collection: token.collectionAddr,
  price: {
    amount,
    denom,
  },
  tokenId,
});

Bundles

The bundler will make a nice package of all your contracts. For example:

const { MinterQueryClient, useMinterConfigQuery } = contracts.Minter;
 
const { CwAdminFactoryClient } = contracts.CwAdminFactory;

Bundler Options

optiondescription
bundle.enabledenable the bundler plugin
bundle.scopename of the scope, defaults to contracts (you can use . to make more scopes)
bundle.bundleFilename of the bundle file

Coding Style

optiondescriptiondefault
useShorthandCtorEnable using shorthand constructor.true

Using shorthand constructor (Might not be transpiled correctly with babel):

  constructor(
    protected address: string | undefined,
    protected cosmWasmClient: CosmWasmClient | undefined,
    protected signingCosmWasmClient: SigningCosmWasmClient | undefined,
    private TSign?: new (
      client: SigningCosmWasmClient,
      sender: string,
      contractAddress: string
    ) => TSign,
    private TQuery?: new (
      client: CosmWasmClient,
      contractAddress: string
    ) => TQuery,
    private TMsgComposer?: new (
      sender: string,
      contractAddress: string
    ) => TMsgComposer
  ) {}

Without using shorthand constructor:

  address: string | undefined;
  ...
  TMsgComposer?: new (
    sender: string,
    contractAddress: string
  ) => TMsgComposer;
 
  constructor(
    address: string | undefined,
    ...
    TMsgComposer?: new (
      sender: string,
      contractAddress: string
    ) => TMsgComposer
  ) {
    this.address = address;
    ...
    this.TMsgComposer = TMsgComposer;
  }

CLI Usage and Examples

Interactive prompt

The CLI is interactive, and if you don't specify an option, it will interactively prompt you.

cosmwasm-ts-codegen generate
? [plugin] which plugins? (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ client
  recoil
  react-query
  message-composer

In this example, you can press space bar to select a number of plugins you wish you enable.

Specifying Plugins

Additionally, it will also show you the name of the field (in this case plugin) so you can specify the parameter (for example when using CI/CD) on the comand line. Here is an exampl with --plugin set to client via CLI:

cosmwasm-ts-codegen generate \
    --plugin client
    --schema ./schema \
    --out ./ts \
    --name MyContractName

You can specify multiple --plugin options using the generate command:

cosmwasm-ts-codegen generate \
          --plugin client \
          --plugin recoil \
          --schema ./schema \
          --out ./ts \
          --name SG721

Bypassing the Prompt

All options can be provided so you can bypass the prompt.

For confirm options, you can pass --no-<name> to set the value to false. Here is an example without optional client, using v3 for react-query, without mutations:

cosmwasm-ts-codegen generate \
    --plugin client \
    --plugin react-query \
    --schema ./schema \
    --out ./ts \
    --name MyContractName \
    --version v3 \
    --no-optionalClient \
    --no-mutations

Example with optional client, using v4, with mutations:

cosmwasm-ts-codegen generate \
    --plugin react-query \
    --schema ./schema \
    --out ./ts \
    --name MyContractName \
    --optionalClient \
    --version v4 \
    --mutations

Types Only Option

If needed, you can generate only the types with the typesOnly option;

cosmwasm-ts-codegen generate \
          --typesOnly \
          --schema ./schema \
          --out ./ts \
          --name SG721

Advanced Usage

for lower-level access, you can import the various plugins directly:

import {
  generateTypes,
  generateClient,
  generateReactQuery,
  generateRecoil,
  generateMessageComposer,
} from "@cosmwasm/ts-codegen";

Example Output

  • cosmwasm-ts-codegen generate --typesOnly

https://gist.github.com/pyramation/107d4e8e30dc5eb3ffc07bc3000f4dd0 (opens in a new tab)

  • cosmwasm-ts-codegen generate --plugin client

https://gist.github.com/pyramation/30508678b7563e286f06ccc5ac384817 (opens in a new tab)

  • cosmwasm-ts-codegen generate --plugin react-query

https://gist.github.com/pyramation/70aef28fd3af0ee164f7711704d3dfc0 (opens in a new tab)

  • cosmwasm-ts-codegen generate --plugin recoil

https://gist.github.com/pyramation/a9520ccf131177b1841e02a97d7d3731 (opens in a new tab)

  • cosmwasm-ts-codegen generate --plugin message-composer

https://gist.github.com/pyramation/43320e8b952751a0bd5a77dbc5b601f4 (opens in a new tab)

  • cosmwasm-ts-codegen generate --plugin message-builder

https://gist.github.com/adairrr/b394e62beb9856b0351883f776650f26 (opens in a new tab)

JSON Schema

We generate code from the JSON Schema (opens in a new tab) exported from CosmWasm smart contracts.

JSON Schema Generation

Currently you have to have the JSON Schema output. Here is an example to start.

First, get the Rust contracts and run cargo build:

git clone git@github.com:public-awesome/stargaze-contracts.git
cd stargaze-contracts
cargo build

now build the schema with cargo schema

cd contracts/sg721/
cargo schema

Exporting Schemas

cosmwasm v1.1 Example

Using the new write_api method, you can export schemas:

use cosmwasm_schema::write_api;
 
use cw4_group::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
 
fn main() {
    write_api! {
        instantiate: InstantiateMsg,
        execute: ExecuteMsg,
        query: QueryMsg,
    }
}

cosmwasm_std Example

Here is a legacy example:

use cosmwasm_std::{Addr, CosmosMsg, Empty};
 
export_schema_with_title(&schema_for!(MinterData), &out_dir, "MinterResponse");
export_schema_with_title(&schema_for!(Addr), &out_dir, "StakingResponse");
export_schema_with_title(&schema_for!(Addr), &out_dir, "DaoResponse");
export_schema_with_title(
      &schema_for!(CosmosMsg<Empty>),
      &out_dir,
      "CosmosMsg_for_Empty",
);

Developing

Initial setup

yarn
yarn bootstrap

Building

yarn build

Tests

Then cd into a package and run the tests

cd ./packages/wasm-ast-types
yarn test:watch

Working with ASTs

See the docs (opens in a new tab) in the ast package.

Related

Checkout these related projects:

Credits

🛠 Built by Cosmology — if you like our tools, please consider delegating to our validator ⚛️ (opens in a new tab)